标签:
Skytree神犇最近在研究中国博大精深的数学。
这时,Sci蒟蒻前来拜访,于是Skytree给Sci蒟蒻出了一道数学题:
给定n个质数,以及k模这些质数的余数。问:在闭区间[a,b]中,有多少个k?最小的k是多少?
Sci蒟蒻数学能力差了Skytree三条街,所以他只好寻求计算机的帮助。他发邮件给同为oier的你,你能帮他解决这个问题吗?
输入第一行为三个正整数n、a、b。
第2到n+1行,每行有两个整数,分别代表第n个质数和k模第n个质数的余数。
输出为两个整数,代表闭区间[a,b]中k的个数和闭区间[a,b]中最小的k。如果k不存在,则输出两个0。
样例1:
3 2 28
3 2
5 3
7 2
样例2:
3 24 31
3 2
5 3
7 2
样例1:
1
23
样例2:
0
0
1<=a<=b<=10^14
n<=10
输入保证所有n个质数的乘积<=10^14
每个质数<=1.5*10^9
请无视通过率(被人黑了。。。)
数据保证不会溢出64bit整数
/* 中国剩余定理 第一次求的ans是最小正整数解 */ #include<cstdio> #include<iostream> #define N 15 #define LL long long using namespace std; LL M[N],m[N],t[N],a[N],sum=1,x,y,la,lb,ans; int n; void e_gcd(LL a,LL b,LL &x,LL &y) { if(b==0) { x=1;y=0; return; } e_gcd(b,a%b,x,y); LL t=x;x=y;y=t-a/b*y; } int main() { cin>>n>>la>>lb; for(int i=1;i<=n;i++) { cin>>m[i]>>a[i]; sum*=m[i]; } for(int i=1;i<=n;i++) { M[i]=sum/m[i]; e_gcd(M[i],m[i],x,y); t[i]=(x+m[i])%m[i]; ans=((ans+(a[i]%sum)*(t[i]%sum)*(M[i]%sum))%sum); } LL tot=0; while(ans<la)ans+=sum; LL temp=ans; while(ans<=lb) { ans+=sum; tot++; } if(!tot)temp=0; cout<<tot<<endl<<temp; return 0; }
标签:
原文地址:http://www.cnblogs.com/harden/p/5658540.html