bzoj3209 花神的數論題

2021-07-10 23:54:35 字數 970 閱讀 8650

題意:求sum(1)*sum(2)*...*sum(n),其中sum(x)表示x的二進位制表達中1的數量。答案模10^7+7。n<=10^15。

考慮列舉sum(x)的值為t,然後求有多少個不大於n的正整數的二進位制表達恰好有t個1,設這個答案為f(t)。

這一部分可以用數字dp來實現。例如要求解1...12,可以將其分成1...7,8...11,12...12這三層。每一層中,滿足範圍內的所有數的字首若干位固定,而字尾若干位(不妨設位len位)可以取遍所有2^len種狀態,即字尾這些位的每一位均可取0或1。設固定的字首已經包含了k個1,則這一層對f(i)(k<=i<=len+k)的貢獻是c(len,i-k),其中c()是組合數。

對每層分別計算貢獻後,答案即為1^f(1)*2^f(2)*...*m^f(m),其中m是n的二進位制表達的位數。這一步用快速冪實現。

需要注意的是,由於f()的值是作為乘方運算中的指數來對答案做貢獻,因此不能對10^7+7取模,而應該對phi(10^7+7)=9988440取模。預處理組合數時也要注意應該對9988440取模。

時間複雜度o((logn)^2)。

**:#include

#include

#define rpt(i,l,r) for(i=l;i<=r;i++)

#define rpd(i,r,l) for(i=r;i>=l;i--)

#define ll long long

#define p 10000007

#define ph 9988440

int c[50][50];

int i,j,k;

int f[50];

ll n,ans;

ll mi(ll x,ll y)

int main()

scanf("%lld",&n);

n++;k=0;

memset(f,0,sizeof(f));

rpd(i,49,0){

if(n&(1ll<

bzoj 3209 花神的數論題

設 sum i 表示 i 的二進位制表示中 1 的個數。給出乙個正整數 n 求 i 1ns um i 枚下1的個數,那麼題目就轉換成了1 n有多少個數的二進位制有x個一。這就很容易數字dp了。f i j 表示i位第一位為1,共j個一的數的數目,g i j 表示i位第一位為0,共j個一的數的數目。容易...

BZOJ3209 花神的數論題

bzoj3209 花神的數論題 背景眾所周知,花神多年來憑藉無邊的神力狂虐各大 oj oi cf tc 當然也包括 ch 啦。描述話說花神這天又來講課了。課後照例有超級難的神題啦 我等蒟蒻又遭殃了。花神的題目是這樣的 設 sum i 表示 i 的二進位制表示中 1 的個數。給出乙個正整數 n 花神要...

bzoj3209 花神的數論題

背景 眾所周知,花神多年來憑藉無邊的神力狂虐各大 oj oi cf tc 當然也包括 ch 啦。描述話說花神這天又來講課了。課後照例有超級難的神題啦 我等蒟蒻又遭殃了。花神的題目是這樣的 設 sum i 表示 i 的二進位制表示中 1 的個數。給出乙個正整數 n 花神要問你派 sum i 也就是 s...