zoukankan      html  css  js  c++  java
  • HDU 4675

    解题思路参考:http://www.cnblogs.com/kuangbin/archive/2013/08/13/3255943.html

    如果gcd(b[1...n])=d,那么b[1...n]中每个b[i]都应是d的倍数,

    而b[1...n]是从a[1...n]修改k个数进而变过来的,

    那么,假设a[1...n]中有cnt个a[i]本来就是d的倍数,

    那么首先 ( n-cnt )个不是d的倍数的必须修改,

    然后,剩下的 cnt 个本来就是d的倍数的a[i]中,我们再挑选 k - ( n - cnt ) 个修改(k个要修改的数,已经修改了 n-cnt 个),就可以满足条件,

    而在小于m的情况下,d的倍数有 l = floor(m/d) 个,

    所以


    所以



    接下来是关于逆元的知识:http://www.cnblogs.com/linyujun/p/5194184.html

     1 #include<cstdio>
     2 #include<cstring>
     3 #define MOD 1000000007
     4 #define MAX 300005
     5 using namespace std;
     6 typedef long long ll;
     7 ll C[MAX],ans[MAX];
     8 int a[MAX],b[MAX],num[MAX];
     9 ll pow(ll a,ll b){
    10     ll r=1,base=a%MOD;
    11     while(b){
    12         if(b&1) r*=base , r%=MOD;
    13         base*=base;
    14         base%=MOD;
    15         b>>=1;
    16     }
    17     return r;
    18 }
    19 ll inv(ll a,ll p){return pow(a, p-2);}//费马求a关于b的逆元
    20 int main()
    21 {
    22     int n,m,k;
    23     while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    24     {
    25         memset(num,0,sizeof(num));
    26         C[n-k]=1;//当cnt=n-k时,C[cnt][n-k]=C[n-k][n-k]=1 
    27         for(int i = n-k+1;i <= n;i++)//当cnt = n-k+1 to n 时,计算C[cnt][n-k]
    28         {
    29             C[i] = C[i-1]*i%MOD*inv(i-(n-k),MOD)%MOD;
    30         }
    31         for(int i=1;i<=n;i++)
    32         {
    33             scanf("%d",&a[i]);
    34             num[a[i]]++;
    35         }
    36         for(int d=m;d>=1;d--)
    37         {
    38             int cnt=0;
    39             ll accu=0;
    40             for(int times=1;times * d <= m;times++)
    41             {
    42                 cnt+=num[times * d];
    43                 if(times > 1) accu = (accu + ans[times *d])%MOD;
    44             }
    45             int l=m/d;
    46             if(l==1)
    47             {
    48                 if(k - (n - cnt) == 0) ans[d]=1;//如果正好有k个不是d的倍数 
    49                 else ans[d]=0;//如果k>(n-cnt),那么剩下的就要在cnt里面找数进行修改,但是这时l==1,因此修改不了;或者k<(n-cnt),这时修改了n-cnt个数,已经超过了k个,不满足 
    50             }
    51             else
    52             {
    53                 if(k < n - cnt) ans[d]=0;
    54                 else
    55                 {
    56                     ll ans_tmp=1;
    57                     ans_tmp=ans_tmp*C[cnt]%MOD;
    58                     ans_tmp=ans_tmp*pow(l-1,k-n+cnt)%MOD;
    59                     ans_tmp=ans_tmp*pow(l,n-cnt)%MOD;
    60                     ans[d]=(ans_tmp-accu+MOD)%MOD;
    61                 }
    62             }
    63         }
    64         for(int d=1;d<=m;d++)
    65         {
    66             if(d>1) printf(" ");
    67             printf("%I64d",ans[d]);
    68         }
    69         printf("
    ");
    70     }
    71 }



  • 相关阅读:
    Java实时读取日志文件
    Trie树的应用:查询IP地址的ISP
    vue.extend,mixins和vue.component的区别
    前端性能优化10个方面
    vue组件和插件是实现
    vue指令用法
    promise retry实现
    linux管道与重定向
    linux文件颜色与类型
    linux文件权限说明
  • 原文地址:https://www.cnblogs.com/dilthey/p/6804141.html
Copyright © 2011-2022 走看看