CRB and Candies
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1049 Accepted Submission(s): 501
He wonders how many combinations he can select.
Can you answer his question for all K (0 ≤
CRB is too hungry to check all of your answers one by one, so he only asks least common multiple(LCM) of all answers.
1 ≤
1 ≤ N ≤
5
1
2
3
4
5
1
2
3
12
10
题目大意:
有一个小孩儿,他有
n
块不同的糖,然后他想吃
块糖的不同方法的最小公倍数。
解题思路:
首先根据题意列出一个公式: ans = LCM(C(n,0),C(n,1)...C(n,n)) ,然后这个公式可以化为: ans = LCM(1,2,...,n+1)(n+1) ,
然后通过这个公式就可以求了,求最小公倍数可以通过素因子分解来计算其实我们可以发现一个规律,举个例子 当 n = 10 的时候:
1 = 1
2 = 2
3 = 3
4 = 22
5 = 5
6 = 2∗3
7 = 7
8 = 23
9 = 32
10 = 2∗5
然后计算
LCM(1,2,...,10)
其实就是主要计算素因子的个数,我们取的是素因子的指数最大的那个数,那么其实我们可以将其化为下列这样的式子:
1 = 1
2 = 2
3 = 3
4 = 2
5 = 5
6 = 0
7 = 7
8 = 2
9 = 3
10 = 0
所以
LCM(1,2,...,10)
就等于上述式子的乘积(不算
0
),那么这样就可以计算了,首先进行素数筛,将
就是类似上面那样计算的,分母可以实现预处理保存在一个数组(也就是逆元数组 Inv )里,这里需要注意的是不能直接计算 LCM(1,2,...,n+1) 因为有取模,直接计算的就会错,
当然可以用高精度试一试,我没有试不知道到底可不可行。
My Code:
/**
2016 - 09 - 02 下午
Author: ITAK
Motto:
今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 1e9+5;
const int MAXN = 1e6+5;
const LL MOD = 1e9+7;
const double eps = 1e-7;
const double PI = acos(-1);
using namespace std;
LL Scan_LL()///输入外挂
{
LL res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
int Scan_Int()///输入外挂
{
int res=0,ch,flag=0;
if((ch=getchar())=='-')
flag=1;
else if(ch>='0'&&ch<='9')
res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
res=res*10+ch-'0';
return flag?-res:res;
}
void Out(LL a)///输出外挂
{
if(a>9)
Out(a/10);
putchar(a%10+'0');
}
void Exgcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
LL x1, y1;
Exgcd(b, a%b, x1, y1);
x = y1;
y = x1 - (a/b)*y1;
}
LL Inv[MAXN];
void Init()
{
Inv[1] = 1;
for(int i=2; i<MAXN; i++)
{
LL x, y;
Exgcd((LL)i, MOD, x, y);
x = (x%MOD+MOD)%MOD;
Inv[i] = x;
}
}
int cnt = 0;
LL p[MAXN];
bool prime[MAXN];
void isprime()
{
memset(prime, 0, sizeof(prime));
cnt = 0;
for(int i=2; i<MAXN; i++)
{
if(!prime[i])
{
p[cnt++] = i;
for(int j=i+i; j<MAXN; j+=i)
prime[j] = 1;
}
}
}
LL lcm[MAXN], vis[MAXN];
void Pre()
{
lcm[1] = 1;
memset(vis, 0, sizeof(vis));
for(int i=0; i<cnt; i++)
{
LL tmp = p[i];
while(tmp < MAXN)
{
vis[tmp] = p[i];
tmp *= p[i];
}
}
for(int i=2; i<MAXN; i++)
{
if(vis[i])
lcm[i] = (lcm[i-1]*vis[i])%MOD;
else
lcm[i] = lcm[i-1]%MOD;
}
}
int main()
{
Init();
isprime();
Pre();
int T, n;
while(~scanf("%d",&T))
{
while(T--)
{
n = Scan_Int();
LL ans = (Inv[n+1]*lcm[n+1])%MOD;
cout<<ans<<endl;
}
}
return 0;
}