zoukankan      html  css  js  c++  java
  • 洛谷 P4317 花神的数论题 || bzoj3209

    https://www.lydsy.com/JudgeOnline/problem.php?id=3209

    https://www.luogu.org/problemnew/show/P4317

    设cnt(x)为x在二进制下1的个数

    很显然,要对于所有k,统计1<=i<=n中cnt(i)==k的i的个数

    可以发现如果x二进制只由1组成,那么可以O(logx)计算出这些数

    因此,可以把[1,n]用数位dp的思想拆开

    对于n二进制中每一个1,试着使得它变为0,那么后面所有二进制位可以任意取,前面取的二进制位都是固定的,可以O(log)求这个范围内的贡献了

    最后n自身要特判

    调试记录:

    1.尝试用求阶乘和阶乘逆元的方法直接求组合数,但是发现找不到如此大的质数,乘法也爆longlong麻烦;事实上在这里也的确比递推组合数麻烦得多

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 #define fi first
     7 #define se second
     8 #define mp make_pair
     9 #define pb push_back
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 typedef pair<int,int> pii;
    13 ll num[120],nt[120];
    14 ll n,m,fac[120],ifac[120],ans=1;
    15 ll c[120][120];
    16 ll poww(ll a,ll b,ll md)
    17 {
    18     ll ans=1,base=a;
    19     for(;b;base=base*base%md,b>>=1)
    20         if(b&1)
    21             ans=ans*base%md;
    22     return ans;
    23 }
    24 void solve(ll n,ll *ans)//n位全1二进制答案
    25 {
    26     for(ll i=0;i<=n;i++)    ans[i]=c[n][i];
    27 }
    28 int main()
    29 {
    30     ll i,j,t;
    31     for(i=0;i<=60;i++)    c[i][0]=1;
    32     for(i=1;i<=60;i++)
    33         for(j=1;j<=i;j++)
    34             c[i][j]=c[i-1][j]+c[i-1][j-1];
    35     scanf("%lld",&n);m=n;
    36     m&=(~1LL);
    37     t=__builtin_popcountll(m);
    38     num[t]++;
    39     if(m!=n)    num[__builtin_popcountll(n)]++;
    40     for(i=2;i<=60;i++)
    41     {
    42         m&=(~(1LL<<(i-1)));
    43         t=__builtin_popcountll(m);
    44         if(n&(1LL<<(i-1)))
    45         {
    46             solve(i-1,nt);
    47             for(j=0;j<=i-1;j++)
    48                 num[j+t]+=nt[j];
    49         }
    50     }
    51     //for(i=1;i<=60;i++)    printf("%lld %lld
    ",i,num[i]);
    52     for(i=1;i<=60;i++)    ans=ans*poww(i,num[i],10000007)%10000007;
    53     printf("%lld",ans);
    54     return 0;
    55 }
  • 相关阅读:
    jUnit4初探(1)
    关于冒泡排序与选择排序
    我对直接插入排序的一点理解
    Java中的Scanner类
    String数组与字符串类
    Redis知识点详解
    MySQL操作命令详解
    java中常见面试题整理
    Redis的安装部署
    zookeeper的伪集群部署步骤
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9363010.html
Copyright © 2011-2022 走看看