5 1 2 3 4 5
1 2 3 12 10
题意:求LCM(C(n,0),C(n,1),C(n,2),...,C(n,n)) (LCM指的是最小公倍数)
思路:一开始想每次求两个数的最小公倍数,然后求得n个数的最小公倍数,结果发现打表打不出= =。看了别人思路,发现求的式子是一个数学公式
令a[n]=LCM(C(n,0),C(n,1),C(n,2),...,C(n,n)) b[n]=LCM(1,2,3,...,n) a[n]=b[n+1]/(n+1) if(n=p^k) bn=p*bn-1 else bn=bn-2 p为素数,符合要求的n如4,8,9,25
所以我们可以先把素数筛选出来,并判断1~n这些数是不是等于p^k,把a[]数组预处理出来,然后用逆元就行了。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; typedef long long ll; typedef long double ldb; #define inf 99999999 #define pi acos(-1.0) #define maxn 1000050 #define MOD 1000000007 int prime[maxn]; ll inv[maxn]; ll a[maxn]; void shake(){ int i; inv[1]=1; for(i=2;i<=1000000;i++){ inv[i]=(MOD-MOD/i)*inv[MOD%i]%MOD; } } ll gcd(ll a,ll b){ return b ? gcd(b,a%b) : a; } int ok(int x) { int t=x,i,j; while(t){ if(t%prime[x]==0)t/=prime[x]; else break; } if(t==1)return 1; else return 0; } void init() { int i,j; for(i=1;i<=1000000;i++)prime[i]=i; for(i=2;i<=1000000;i++){ if(prime[i]==i){ for(j=i+i;j<=1000000;j+=i){ prime[j]=i; } } } a[1]=1; for(i=2;i<=1000000;i++){ if(ok(i)){ a[i]=a[i-1]*prime[i]%MOD; } else a[i]=a[i-1]; } } int main() { int T,i,j; ll n,m,ans,num; shake(); init(); scanf("%d",&T); while(T--) { scanf("%lld",&n); printf("%lld\n",a[n+1]*inv[n+1]%MOD ); } return 0; }