P4317 花神的数论题
原题
题意:给定一个数 \(n(1<=n<=1e18)\) ,若 \(\operatorname{sum}(x)\) 为在二进制下 \(x\) 为 \(1\) 的位数的个数,求 \(\prod_{i=1}^{n}\operatorname{sum}(i)\mod (1e7+7)\) 的结果
如果直接考虑数位DP,会发现转移很麻烦(当然如果你硬推出来了当我没说),所以可以换个思路
不难发现,\(n\) 在二进制下最多有 \(64\) 位,所以可以数位DP算出来 \(cnt[k]\) 表示 \(\operatorname{sum}(x)=k\) 的个数,再将 \(ans*=k^{cnt[k]}\)即可,由于这里的指数可能会很大,所以需要快速幂
注:在数位DP时,一定不要取模,因为DP值是指数,而众所周知指数是不能取模的(本人因为取模调了三小时)
\(ACcode:\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int mod=1e7+7;
ll n;
ll dp[70][2][70];
ll dfs(int step,bool limit,int cnt)
{
if(cnt<0) return 0;
if(dp[step][limit][cnt]!=-1) return dp[step][limit][cnt];
if(step==1)
{
if(cnt>=2)
{
dp[step][limit][cnt]=0;
return 0;
}
if(limit&&!(n&1)&&cnt==1)
{
dp[step][limit][cnt]=0;
return 0;
}
dp[step][limit][cnt]=1;
return 1;
}
if(limit)
{
if((n>>(step-1))&1) dp[step][1][cnt]=dfs(step-1,0,cnt)+dfs(step-1,1,cnt-1);
else dp[step][1][cnt]=dfs(step-1,1,cnt);
}
else
{
dp[step][0][cnt]=dfs(step-1,0,cnt-1)+dfs(step-1,0,cnt);
}
return dp[step][limit][cnt];
}
ll qpow(ll a,ll p)
{
ll x=1,y=a;
while(p)
{
if(p&1) x=(x*y)%mod;
y=(y*y)%mod;
p>>=1;
}
return x%mod;
}
ll ans=1;
signed main()
{
cin>>n;
memset(dp,-1,sizeof(dp));
for(int i=1;i<=64;i++)
{
ans=(ans*qpow(i,dfs(64,1,i)))%mod;
}
cout<<ans<<"\n";
return 0;
}

浙公网安备 33010602011771号