zoukankan      html  css  js  c++  java
  • bzoj3209: 花神的数论题(数位DP)

    3209: 花神的数论题

    题目:传送门 

    题解:

       要注意到有可能同一个sum有多个的情况

       定义一个 f[i][j] 和 g[i][j] 表示:

       二进制位数位i,最高位为0,共有j个1  &&  二进制位数位i,最高位为1,共有j个1

       转移很简单就不说了。

       

       这样子就可以瞎枚举一下n的二进制位,如果为1就快速幂计算一下答案(细节很多,具体看代码)

    奇丑无比的代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long LL;
     8 const LL mod=10000007;
     9 LL f[110][110],g[110][110];//共i位,最高位为 0/1 ,共j个1 
    10 LL n;
    11 LL p_m(LL a,LL b)
    12 {
    13     LL ans=1;
    14     while(b!=0)
    15     {
    16         if(b%2==1)ans=(ans*a)%mod;
    17         b/=2;a=(a*a)%mod;
    18     }
    19     return ans;
    20 }
    21 int main()
    22 {
    23     scanf("%lld",&n);LL len=0;
    24     LL x=n;while(x){x/=2;len++;}
    25     f[1][0]=1;g[1][1]=1;
    26     for(int i=2;i<=len;i++)
    27         for(int j=0;j<=i;j++)
    28         {
    29             f[i][j]=f[i-1][j]+g[i-1][j];
    30             if(j)g[i][j]=f[i-1][j-1]+g[i-1][j-1];
    31         }
    32     LL ans=1,sum=0;
    33     for(int k=len;k>=1;k--)
    34     {
    35         if(1LL<<(k-1)&n)
    36         {
    37             for(int i=1;i<=k;i++)ans=(ans*p_m(i+sum,f[k][i]))%mod;
    38             if(sum)ans=(ans*sum)%mod;
    39             sum++;
    40         }
    41     }
    42     printf("%lld
    ",(ans*sum)%mod);
    43     return 0;
    44 }
  • 相关阅读:
    CopyOnWriteArrayList源码阅读笔记
    ArrayList源码阅读笔记
    MySQL和Oracle的区别
    思维导图概览SpringCloud
    Java学习之Request篇
    Java学习之servlet篇
    Java学习之数据库连接池
    Java学习之注解篇
    Java爬取先知论坛文章
    Java学习之爬虫篇
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8483009.html
Copyright © 2011-2022 走看看