BZOJ3290 花神的數論題

2021-07-09 20:49:59 字數 1447 閱讀 9238

3209: 花神的數論題

time limit: 10 sec memory limit: 128 mb

description

背景 眾所周知,花神多年來憑藉無邊的神力狂虐各大 oj、oi、cf、tc …… 當然也包括 ch 啦。

描述 話說花神這天又來講課了。課後照例有超級難的神題啦…… 我等蒟蒻又遭殃了。

花神的題目是這樣的

設 sum(i) 表示 i 的二進位制表示中 1 的個數。給出乙個正整數 n ,花神要問你

派(sum(i)),也就是 sum(1)—sum(n) 的乘積。

input

乙個正整數 n。

output

乙個數,答案模 10000007 的值。

sample input

樣例輸入一

sample output

樣例輸出一

hint

對於樣例一,1*1*2=2;

資料範圍與約定

對於 100% 的資料,n≤10^15

source

原創 memphis

一開始想的是能不能用數字dp做:用f(i,j)表示二進位制位數共i位且一共有j個1的數的個數——當然是可以的,然而細細分析之後發現有更加簡便的做法。我們考慮數n的二進位制,假設共l位,分別分別為b0 b1 b2…bl-1。為了計算出最終答案我們只需要統計出二進位制中1的個數分別為1,2,…,l的數的個數。我們從高位往地位進行計算,若n的bi=1,那麼對於那些bi=0的數,我們可以直接將他們對答案的貢獻計算出來,即:設i之前有m個1,i之後還有k位,那麼對於任意0<=j<=k,我們便找到了c(k,j)(這是組合數= =)個總共有m+j個1的數。最終不要忘記了算上n本身也要計入答案。統計出所有的個數後,使用快速冪求解即可。注意:10000007不是質數,此題題不能也沒必要使用費馬小定理……

#include

#define bit(a) (1llnamespace

std;

const

int p=10000007;

typedef

unsigned

long

long ll;

ll c[60][60],cnt[60];

void add(int l,int pre)

ll fpow(ll a,ll b)

int main()

ll n;

cin>>n;

int l=0;

while(bit(l)<=n)l++;

int pre=0;

for(int i=l-1;~i;i--)if(bit(i)&n)add(i,pre++);

cnt[pre]++;

ll ans=1;

for(int i=1;i<=l;i++)ans=ans*fpow(i,cnt[i])%p;

cout

0;}

bzoj3209 花神的數論題

題意 求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...

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 花神要...