zoukankan      html  css  js  c++  java
  • DP,数论————洛谷P4317 花神的数论题(求1~n二进制中1的个数和)

    玄学代码(是洛谷题解里的一位dalao小粉兔写的)

    //数位DP(二进制)计算出f[i]为恰好有i个的方案数。
    //答案为∏(i^f[i]),快速幂解决。
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int mod=10000007;
    ll n,ans=1;
    ll c,f[50];
    ll qpow(ll b,ll e){
        ll a=1;
        for(;e;b=b*b%mod,e>>=1)
            e&1?a=a*b%mod:0;
        return a;
    }
    
    int main(){
        scanf("%lld",&n);
        for(int j=49;~j;--j){
            for(int i=49;i;--i)
                f[i]+=f[i-1];
            if(n>>j&1)++f[c++];
        }++f[c];
        for(int i=1;i<=49;++i)
            ans=ans*qpow(i,f[i])%mod;
        printf("%lld",ans);
        return 0;
    }

    下面是另一位dalaoStyx写的简单易懂的题解

    代码如下

    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define mod 10000007
    using namespace std;
    
    long long ans=1,n,k,cnt,dp[110][110];
    
    long long kasumi(long long a,long long b)
    {
        long long tmp=1;
        while(b)
        {
            if(b&1) tmp=(tmp%mod)*a%mod;
            a=(a%mod)*a%mod;
            b>>=1;
        }
        return tmp%mod;
    }
    
    int main()
    {
        scanf("%lld",&n);
        for(int i=1; i<=60; i++)
        {
            dp[i][1]=1;
        }
        for(int i=1; i<=60; i++)
        {
            dp[i][i]=1;
        }
        for(int i=2; i<=60; i++)
        {
            for(int j=2; j<i; j++)
            {
                dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
            }
        }
        for(k=1; k<=n; k<<=1)
        {
            n-=k;
            cnt++;
            for(int j=1; j<=cnt; j++)
            {
                ans=(ans%mod)*kasumi(j,dp[cnt][j])%mod;
                ans%=mod;
            }
        }
        cnt=0;
        for(int i=60;i>=0;i--)
        {
            if((1ll<<i)<=n)
            {
                for(int j=1;j<=i+1;j++)
                {
                    ans=(ans%mod)*kasumi(j+cnt,dp[i+1][j]);
                    ans%=mod;
                }
                cnt++;
                n-=(1ll<<i);
            }
        }
        printf("%lld
    ",ans);
    }

    至于为什么不用扩展欧拉定理降幂,那是因为杨辉三角在总和等于1e15的时候 ,每一个数肯定不会爆longlong

  • 相关阅读:
    第三章 读书笔记
    第一章 读书笔记
    第二章 读书笔记
    第九章
    第十章
    第8章 蜂鸣器
    第7章 led闪烁
    第6章 第一个Linux驱动程序:统计单词个数
    第5章 搭建S3C6410开发板环境
    第3章 Git使用入门
  • 原文地址:https://www.cnblogs.com/myhnb/p/11367363.html
Copyright © 2011-2022 走看看