标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5407
题意:给定一个数n,求LCM(C(n,0),C(n,1),C(n,2)...,C(n,n))
根据官方题解,g(n) = LCM(C(n,0),C(n,1),C(n,2)...,C(n,n))
g(n) = f(n+1)/(n+1)
而 f(n) = LCM(1,2,3,...,n)
对于f(n)中的每一个数,对LCM的贡献值并不一样,可以想一下,对n进行因式分解,n = p1^x1*p2^x2*...+pt*xt;比n小的数中必然有p1^x1,p2^x2...
所以,只有当n可以分解为n=p^x的时候,才对LCM值有贡献。
#include<iostream> #include<cstdio> #include<cstring> typedef long long LL; using namespace std; const int mod = 1e9+7; const int MAXN=1e6+10; int prime[MAXN+1]; int ans[MAXN]; int fra[MAXN]; // 打印素数表 bool notprime[MAXN];//值为false表示素数,值为true表示非素数 void init1() { memset(notprime,false,sizeof(notprime)); notprime[0]=notprime[1]=true; for(int i=2;i<MAXN;i++) if(!notprime[i]) { if(i>MAXN/i)continue;//防止后面i*i溢出(或者i,j用long long) //直接从i*i开始就可以,小于i倍的已经筛选过了,注意是j+=i for(int j=i*i;j<MAXN;j+=i) notprime[j]=true; } } void getPrime() { memset(prime,0,sizeof (prime)); for(int i=2;i<=MAXN;i++) { if(!prime[i])prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&prime[j]<=MAXN/i;j++) { prime[prime[j]*i]=1; if(i%prime[j]==0) break; } } } // 求逆元 long long inv(long long a,long long mod) { if(a == 1)return 1; return inv(mod%a,mod)*(mod-mod/a)%mod; } void init2(){ ans[1] = 1; int i, j; for( i = 2; i < MAXN; i++){ int tmp = i+1; bool flag = false; for( j = 1; prime[j]*prime[j]<= i+1; ++j){ while( tmp % prime[j] == 0 ){ tmp /= prime[j]; flag = true; } if(flag) break; } if(tmp == 1){ ans[i] = 1LL*ans[i-1]*i%mod*prime[j]%mod*inv((i+1),mod)%mod; } else if(!notprime[i+1]){ ans[i] = 1LL*ans[i-1]*i%mod*(i+1)%mod*inv((i+1),mod)%mod; } else{ ans[i] = 1LL*ans[i-1]*i%mod*inv((i+1),mod)%mod; } } } int main(){ getPrime(); init1(); init2(); int T, N; scanf("%d",&T); while(T--){ scanf("%d",&N); printf("%d\n",ans[N]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/blueprintf/p/4852490.html