Problem 1753 Another Easy Problem
Accept: 400 Submit: 1804
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
小TT最近学习了高斯消元法解方程组,现在他的问题来了,如果是以下的方程,那么应该如何解呢?
C(n1,m1)==0 (mod M)
C(n2,m2)==0 (mod M)
C(n3,m3)==0 (mod M)
................
C(nk,mk)==0 (mod M)
小TT希望你告诉他满足条件的最大的M
其中C(i,j)表示组合数,例如C(5,2)=10,C(4,2)=6...
Input
输入数据包括多组,每组数据的第一行是一个正整数T(1<=T<=150)表示接下来描述的T个方程
接下来T行,每行包括2个正整数ni,mi (1<=mi<=ni<=100000)
Output
输出一行答案,表示满足方程组的最大M。
Sample Input
3100 150 160 1
Sample Output
10
Source
FZU 2009 Summer Training IV--Number Theory
解题报告: 个人觉得题目出的不是太严谨,没有给出结果的数据范围。如果输入数据是
1
100000 50000
那么结果有7000+多位。这题的话unsigned long long 可以搞定。
优化的地方是进行素数判断时,素数大于最小的n时就不用判断了。注意输出用I64u
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long LLU;
const int maxn = 100001;
int prime[maxn];
int primeNum;
bool h[maxn];
void calPrime()
{
for(int i=2;i<maxn;i++) if(!h[i])
{
prime[primeNum++]=i;
for(int j=i+i;j<maxn;j+=i) h[j]=true;
}
}
int calN(int n, int k)
{
int res=0;
while(n>=k)
{
n/=k;
res+=n;
}
return res;
}
LLU powLLU(LLU a, int b)
{
LLU res=1;
while(b)
{
if(b&1)
res = res*a;
a = a*a;
b>>=1;
}
return res;
}
int num[155];
int kk[155];
void work(int n)
{
int limit = maxn;
for(int i=0;i<n;i++)
scanf("%d%d", num+i, kk+i), limit=min(limit, num[i]);
LLU ans=1;
for(int i=0;prime[i]<=limit && i<primeNum;i++)
{
int t=maxn;
for(int j=0;j<n;j++)
t=min(t, calN(num[j], prime[i])-calN(kk[j], prime[i])-calN(num[j]-kk[j], prime[i]));
if(t!=maxn)
ans*=powLLU(prime[i], t);
}
printf("%I64u\n", ans);
}
int main()
{
calPrime();
int n;
while(~scanf("%d", &n))
work(n);
}