题目大意:设 sum(i) 表示 i 的二进制表示中 1 的个数
求sum(1)—sum(N) 的乘积
题解:因为1的个数最多64,很容易想到求有多少个数二进制中1的个数为i,然后快速幂
数位dp随便求求就好
我的收获:看问题的角度
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=10000007;
ll n;
ll f[60][60];
int li[60];
ll dfs(int i,int state,bool limit)
{
if (state>i) return 0;
if (i==0&&state==0) return 1;
if (i==0) return 0;
if (!limit && f[i][state]!=-1) return f[i][state];
int up=limit? li[i]:1;
ll ans=0;
for (int j=0;j<=up;j++)
switch (j)
{
case 1:ans+=dfs(i-1,state-1,limit&&j==li[i]);break;
case 0:ans+=dfs(i-1,state,limit&&j==li[i]);break;
}
if (!limit) f[i][state]=ans;
return ans;
}
ll power_mod(ll a,ll k)//注意强制类型转换!!,既然mod那么大!就很有可能会超int,power_mod必须要很注意加ll
{
ll ans=1;
while (k)
{
if (k&1) ans=ans*a%mod;
a=a*a%mod;
k>>=1;
}
return ans;
}
void work(ll n)
{
memset(f,-1,sizeof(f));
int tot=0;
while (n)
{
li[++tot]=n&1;
n>>=1;
}
ll ans=1,k;
for (int i=1;i<=tot;i++)
{
k=dfs(tot,i,true);
if (k) ans=ans*power_mod(i,k)%mod;
}
printf("%lld",ans);
}
int main()
{
scanf("%lld",&n);
work(n);
return 0;
}