Shu-How Zの小窝

Loading...

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;
}
posted @ 2025-02-26 19:13  wangyanxiao  阅读(22)  评论(0)    收藏  举报