您的位置:首页 > 其它

(hdu1573)X问题(中国剩余定理+扩展欧几里得算法)

2017-07-26 09:42 761 查看
X问题

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 6595 Accepted Submission(s): 2287

Problem Description

求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], …, X mod a[i] = b[i], … (0 < a[i] <= 10)。

Input

输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为两个正整数N,M (0 < N <= 1000,000,000 , 0 < M <= 10),表示X小于等于N,数组a和b中各有M个元素。接下来两行,每行各有M个正整数,分别为a和b中的元素。

Output

对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。

Sample Input

3

10 3

1 2 3

0 1 2

100 7

3 4 5 6 7 8 9

1 2 3 4 5 6 7

10000 10

1 2 3 4 5 6 7 8 9 10

0 1 2 3 4 5 6 7 8 9

Sample Output

1

0

3

Author

lwg

Source

HDU 2007-1 Programming Contest

分析:按照题意,X符合X=Ai*x+Bi,即X=Bi (mod Ai),中国剩余定理的经典例题

注意:其中Ai可能不互质

利用中国剩余定理(不互质)的模板,详解见:http://blog.csdn.net/feng_zhiyu/article/details/76098909

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
LL x,y,gcd;
int a[10],b[10];
LL ext_gcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
LL d=ext_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,flag=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
scanf("%d",&a[i]);
for(int i=1; i<=m; i++)
scanf("%d",&b[i]);
LL n1=a[1],n2,r,p=b[1];
for(int i=2; i<=m; i++)
{
n2=a[i];
r=b[i]-p;
gcd=ext_gcd(n1,n2,x,y);///n1*x+n2*y=gcd(n1,n2);
if(r%gcd!=0)///gcd不能整除r,则方程无解
{
flag=1;
puts("0");
break;
}
x=x*r/gcd;///n1*x+n2*(r/gcd*y)=r
LL t=abs(n2/gcd);///取绝对值是gcd可能为负,进而t为负,不加绝对值就WA!!!
x=(x%t+t)%t;///求的n1*x+n2*y=r的通解为x=x0+t*k(k为任意整数),最小解则取模
p=x*n1+p;///p为X=a[i]*x+b[i]的X其中的一个解
n1=a[i]/gcd*n1;///lcm(a[1],a[2],....,a[i]);i<=m
printf("%lld  %lld\n",p,n1);
}
if(!flag)
{
LL ans=(p%n1+n1)%n1,cnt=0;///X=ai*k+bi,ans为X的最小非负数解
if(ans>0&&ans<=n) cnt++;///判断是否符合题目条件(小于等于n的正整数)
cnt+=(n-ans)/n1;///加上(ans,n]的解的个数
printf("%lld\n",cnt);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息