CRB and Candies
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1291 Accepted Submission(s): 624
Problem Description
CRB has N different candies. He is going to eat K candies.
He wonders how many combinations he can select.
Can you answer his question for all K(0 ≤ K ≤ N)?
CRB is too hungry to check all of your answers one by one, so he only asks least common multiple(LCM) of all answers.
Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case there is one line containing a single integer N.
1 ≤ T ≤ 300
1 ≤ N ≤ 106
Output
For each test case, output a single integer – LCM modulo 1000000007(109+7).
Sample Input
5 1 2 3 4 5
Sample Output
1 2 3 12 10
题意:
求C(n,1),C(n,2),…,C(n,n)的最小公倍数对1000000007取模(n<1e6+1)
思路:
- Kummer定理:对于C(n,i), i≤n,假设在p进制下,n-i发生了k次借位,或者(n-i)+i发生了k次进位,那么p^k是C(n,i)的约数
- 一个很好推的性质:C(n,i)中不存在大于n的质因子
有了上面那个定理后,这道题就好做了
对于每一个质数p,求出他在哪个组合数C(n,x)中满足p^k|C(n,x),k最大,最后答案就是∏p^k
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int cnt, flag[1000005] = {1,1}, pri[88888], str[25];
LL Pow(LL a, int b)
{
LL ans = 1;
while(b)
{
if(b%2)
ans = ans*a%mod;
a = a*a%mod;
b /= 2;
}
return ans;
}
void Primeset()
{
LL i, j;
for(i=2;i<=1000000;i++)
{
if(flag[i])
continue;
for(j=i*i;j<=1000000;j+=i)
flag[j] = 1;
pri[++cnt] = i;
}
}
int Jud(int n, int p)
{
int i, flag, sum, len;
len = flag = sum = 0;
while(n)
{
str[++len] = n%p;
n /= p;
}
for(i=1;i<=len-1;i++)
{
if(str[i]-flag<p-1)
{
sum++;
flag = 1;
}
}
return sum;
}
int main(void)
{
LL ans;
int T, n, i;
Primeset();
scanf("%d", &T);
while(T--)
{
ans = 1;
scanf("%d", &n);
for(i=1;i<=cnt;i++)
ans = ans*Pow(pri[i], Jud(n, pri[i]))%mod;
printf("%lld\n", ans);
}
}