P4317 花神的数论题

题意简述

\(\text{sum}(i)\)\(i\)的二进制中\(1\)的个数,求

\[\prod_{i = 1} ^ n \text{sum}(i) \]

\(n \le 10 ^ {15}\)

简单口胡

考虑对每个数求\(\text{sum}(i)\)肯定是不行的,只能考虑将思维转到求“有多少数的\(\text{sum}(i) = x\),然后对\(x\)进行操作,因为\(\text{sum}(i)\)的最大值也就\(50\)左右,大大降低复杂度。

具体地,考虑求出\(\text{S}_i = \sum_{k = 1} ^ n {[\text{sum}(k) = i]}\),答案即为

\[\prod_{i = 1} ^ {\log{n}} i ^ {\text{S}_i} \]

考虑数位\(\text{dp}\),设\(\text{dfs}(n,cnt,now)\)为当前在第\(now\)位,当前有\(cnt\)位为\(1\),目标要求\(n\)为为\(1\)的答案。

记忆化搜索,记得要反着搜。

别忘了必要的剪枝。

# include <bits/stdc++.h>
using namespace std;
long long x;
const long long mod = 10000007;

const int M = 52;

long long dp[M][M][M];

int N;
int a[M];
long long q[M];

long long dfs(int n,int cnt,int now,bool op)
{
    // printf("n = %d,cnt = %d,now = %d,op = %d\n",n,cnt,now,op);
    if(now == -1) return cnt == n;
    if(cnt + now + 1 < n) return dp[n][cnt][now] = 0;
    if(!op && dp[n][cnt][now] != -1) return dp[n][cnt][now];
    int limit = (op == 1) ? a[now] : 1;
    long long ans = 0;
    for(int i = 0; i <= limit; i++)
    {
        ans = ans + dfs(n,cnt + (1 == i),now - 1,op && i == limit);
    }
    if(!op) dp[n][cnt][now] = ans;
    return ans;
}

long long qmulti(long long x,long long p)
{
    long long ans = 1;
    while(p)
    {
        if(p & 1) 
        {
            ans = (ans * x) % mod;
        }
        p >>= 1;
        x = (x * x) % mod;
    }
    return ans;
}

void solve(void)
{
    N = log2(x);
    for(int i = N; i >= 0; i--) 
    {
        if((x >> i) & 1) a[i] = 1;
    }
    // printf("N = %d\n",N);
    // printf("Yes:chaifen\n");
    N++;
    for(int i = N; i >= 1; i--)
    {
        memset(dp,-1,sizeof(dp));
        // printf("i = %d\n",i);
        q[i] = dfs(i,0,N - 1,1);
        // printf("q[%d] = %lld\n",i,q[i]);
    }
    // printf("Yes:q\n");
    long long ans = 1;
    for(int i = N; i >= 1; i--)
    {
        ans = (ans * qmulti(i,q[i]))% mod;
    }
    printf("%lld\n",ans);
}

int main(void)
{
    scanf("%lld",&x);
    solve();
    return 0;
}

posted @ 2020-11-13 21:15  luyiming123  阅读(77)  评论(1编辑  收藏  举报