BZOJ 3209 花神的數論題 數字dp

2022-05-12 21:21:43 字數 1840 閱讀 2289

description

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

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

花神的題目是這樣的

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

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

input

乙個正整數 n。

output

乙個數,答案模 10000007 的值。

sample input

樣例輸入一

3sample output

樣例輸出一

2hint

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

資料範圍與約定

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

思路:數字dp,計算小於n並且sum(i)=k的i有多少個,設為u,則答案為pow(k,u),然後列舉k即可

#include

#include

#include

#include

#define maxn 1000005

#define mod 10000007

using namespace std;

long long num[maxn],h=0,dp[100][100][100][2];

long long dfs(long long pos,long long need,long long now,long long limit)

if(pos==0)return now==need;

int tmp=limit?num[pos]:1;

long long ans=0;

if(!limit&&dp[pos][need][now][limit]!=-1)

return dp[pos][need][now][limit];

for(int i=0;i<=tmp;i++)

ans=(ans+dfs(pos-1,need,now+i,limit&&(i==tmp)));

if (!limit)

dp[pos][need][now][limit]=ans;

return ans;

long long mpow(long long a,long long n)

long long ans=1;

a%=mod;

while (n)

if (n%2) ans=(ans%mod)*(a%mod)%mod;

n/=2;

a=(a%mod)*(a%mod)%mod;

return ans;

int main()

long long n;

memset(dp,-1,sizeof(dp));

while(scanf("%lld",&n)!=eof)

long long ans=1;h=0;

if(n==0)

while(n>0)

for(int i=1;i<=h;i++)

long long u=dfs(h,i,0,1);

long long v=mpow((long long)i,u%9988440+9988440);

ans=((ans%mod)*(v%mod))%mod;

if(ans==6296768)

int zz=1;

printf("%lld\n",ans);

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