【题解】
数位dp的思想
枚举的是二进制数 先预处理出所有i位二进制数中,含j个1的数的个数,就是C(i,j)
然后就是从高位到低位,处理填0还是1的情况
填0:之后i-1位随机填0/1
填1:紧接着的[n对应的二进制数该位为0]的位只能填0(否则超过n)
注意该算法计数到的所有情况不含SUM(n)!因此读入时,n++
数位dp是不是基本都要预处理 = =
#include<stdio.h>
#include<stdlib.h>
#define MOD 10000007
typedef unsigned long long ULL;
ULL c[65][65]={0};
ULL ksm(ULL a,ULL n)
{
ULL ans;
a%=MOD;
if(n==0) return 1;
if(n==1) return a;
ans=ksm(a,n/2);
ans=(ans*ans)%MOD;
if(n%2==1) ans=(ans*a)%MOD;
return ans;
}
int main()
{
ULL n,t,ans=1;
int i,j,k=0,len=0;
scanf("%llu",&n);
n++;
for(i=0;i<64;i++)//预处理组合数
{
c[i][0]=1;
for(j=1;j<i;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
c[i][i]=1;
}
for(t=n;t>0;t=t>>1)
len++;
for(i=len;i>=1;i--)
if(n>>(i-1)&1)
{
for(j=0;j<i;j++)
if(j+k!=0) ans=(ans*ksm(j+k,c[i-1][j]))%MOD;//若这一位填0(比它高的位数能填1的都已经填了1)
k++;//若这一位填1(k:之前填了k个1)
}
printf("%llu",ans);
return 0;
}