5 1 2 3 4 5
1 2 3 12 10
当时做这个题的时候,感觉组合数都求不出来,当然了,求出来再取最小公倍数也超时了。搜题解 搜出来一个Krummer定理,这是什么鬼@。@
百度百科:设m,n为正整数,p为素数,则C(下m+n上m)含p的幂次等于m+n在p进制下的进位次数。
这个和这个题有什么关系呢?听我细细道来……这个题是要求C(n,k) (k从0到n)这n+1个数的最小公约数,那么,根据唯一分解定理可知,在这些数里,想找某质数的最大幂次,就
需要找到一个k使得进位的次数最多,当然了 k具体是什么我们不需要知道 ~_~ 但是我们需要根据n推测出进位的是哪位,既然是进了位的,那么这位在p进制下一定是小于k-1的,
后面的数都进位,那么才会是最大的幂次。
#include <iostream> #include<cstdio> #include<cstring> #define N 1000004 using namespace std; const int MOD = 1e9 + 7; bool vis[N]; int prime[N/4],idx; void init() { idx=0; memset(vis,1,sizeof(vis)); for(int i=2;i<N;i++) { if(vis[i]) { prime[idx++]=i; for(int j=1;j*i<N;j++) vis[j*i]=0; } } } long long pow_mod(long long a,int k) { long long ans=1;//这里需要long long 毕竟10^9…… while(k>0) { if(k&1) ans=ans*a%MOD; a=a*a%MOD; k>>=1; } return ans; } int get_pow(int n,int p) { int tmp[30],ans=0; while(n>0) { tmp[ans++]=n%p; n/=p; } int flag=0,res=0; for(int i=0;i<ans-1;i++) { if(tmp[i]<p-1+flag) { flag=1; res++; } } return res; } int main() { // freopen("cin.txt","r",stdin); int t,n; long long ans; scanf("%d",&t); init(); while(t--) { scanf("%d",&n); ans=1; for(int i=0;i<idx&&prime[i]<=n;i++) { ans=(ans*pow_mod(prime[i],get_pow(n,prime[i])))%MOD; } printf("%I64d\n",ans); } return 0; }