poj1061 扩展欧几里得解方程
#include<iostream> #include<cstdlib> #include<stdio.h> using namespace std; __int64 exGcd(__int64 a,__int64 b, __int64 &xx, __int64 &yy); int main() { __int64 x,y,m,n,L,xx,yy; scanf("%I64d%I64d%I64d%I64d%I64d",&x,&y,&m,&n,&L); __int64 d=exGcd(n-m,L,xx,yy);//a,n,x,y ax+ny=b;(n-m)*xx+l*yy=x-y; if((x-y)%d!=0) cout<<"Impossible"<<endl; else { xx=xx*((x-y)/d); int s=L/d; xx=(xx%s+s)%s; printf("%I64d\n",xx); /* xx=(x-y)/d*xx%L+L; printf("%I64d\n",xx%(L/d));*/ /*e = b / d * x % n + n; return e % (n / d);*/ } system("PAUSE"); return 0; } __int64 exGcd(__int64 a,__int64 b, __int64 &xx, __int64 &yy) { if(b == 0) { xx = 1; yy = 0; return a; } __int64 r = exGcd(b, a % b, xx, yy); __int64 t = xx; xx = yy; yy = t - a / b * yy; return r; }
Poj2115
C Looooops
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11401 Accepted: 2700
Description
A Compiler Mystery: We are given a C-language style for loop of type
for (variable = A; variable != B; variable += C)
statement;
I.e., a loop which starts by setting variable to value A and while variable is not equal to B, repeats statement followed by increasing the variable by C. We want to know how many times does the statement get executed for particular values of A, B and C, assuming that all arithmetics is calculated in a k-bit unsigned integer type (with values 0 <= x < 2k) modulo 2k.
Input
The input consists of several instances. Each instance is described by a single line with four integers A, B, C, k separated by a single space. The integer k (1 <= k <= 32) is the number of bits of the control variable of the loop and A, B, C (0 <= A, B, C < 2k) are the parameters of the loop.
The input is finished by a line containing four zeros.
Output
The output consists of several lines corresponding to the instances on the input. The i-th line contains either the number of executions of the statement in the i-th instance (a single integer number) or the word FOREVER if the loop does not terminate.
Sample Input
3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0
Sample Output
0
2
32766
FOREVER
这题与上题大同小异。
根据题意,我们有A+CX=B(mod M) M=1<<k
cx+2^ky=b-a #include<iostream> #include<cstdlib> #include<stdio.h> #include<math.h> using namespace std; __int64 exGcd(__int64 a,__int64 b, __int64 &xx, __int64 &yy); int main() { __int64 xx,yy,a,b,c,k; while(scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&k)!=EOF) { if(a==0&&b==0&&c==0&&k==0) break; k=pow(2,k+0.0); __int64 d=exGcd(c,k,xx,yy);//a,n,x,y ax+ny=b;(n-m)*xx+l*yy=x-y; if((b-a)%d!=0) cout<<"FOREVER"<<endl; else { /*xx=xx*((x-y)/d); int s=L/d; xx=(xx%s+s)%s; printf("%I64d\n",xx);*/ xx=(b-a)/d*xx%k+k; printf("%I64d\n",xx%(k/d)); /*e = b / d * x % n + n; return e % (n / d);*/ } } // system("PAUSE"); return 0; } __int64 exGcd(__int64 a,__int64 b, __int64 &xx, __int64 &yy) { if(b == 0) { xx = 1; yy = 0; return a; } __int64 r = exGcd(b, a % b, xx, yy); __int64 t = xx; xx = yy; yy = t - a / b * yy; return r; }
Poj2142
The Balance
Time Limit:5000MS |
Memory Limit:65536K |
|
Total Submissions:2337 |
Accepted:1012 |
Description
Ms. Iyo Kiffa-Australis has a balance and only two kinds of weights to measure a dose of medicine. For example, to measure 200mg of aspirin using 300mg weights and 700mg weights, she can put one 700mg weight on the side of the medicine and three 300mg weights on the opposite side (Figure 1). Although she could put four 300mg weights on the medicine side and two 700mg weights on the other (Figure 2), she would not choose this solution because it is less convenient to use more weights.
You are asked to help her by calculating how many weights are required.
Input
The input is a sequence of datasets. A dataset is a line containing three positive integers a, b, and d separated by a space. The following relations hold: a != b, a <= 10000, b <= 10000, and d <= 50000. You may assume that it is possible to measure d mg using a combination of a mg and b mg weights. In other words, you need not consider "no solution" cases.
The end of the input is indicated by a line containing three zeros separated by a space. It is not a dataset.
Output
The output should be composed of lines, each corresponding to an input dataset (a, b, d). An output line should contain two nonnegative integers x and y separated by a space. They should satisfy the following three conditions.
· You can measure dmg using x many amg weights and y many bmg weights.
· The total number of weights (x + y) is the smallest among those pairs of nonnegative integers satisfying the previous condition.
· The total mass of weights (ax + by) is the smallest among those pairs of nonnegative integers satisfying the previous two conditions.
No extra characters (e.g. extra spaces) should appear in the output.
Sample Input
700 300 200
500 200 300
500 200 500
275 110 330
275 110 385
648 375 4002
3 1 10000
0 0 0
Sample Output
1 3
1 1
1 0
0 3
1 1
49 74
3333 1
这题跟上面的比起来稍微有点麻烦。
大概意思 给定 a b k找到满足ax+by=k的令|x|+|y|最小(等时令a|x|+b|y|最小)不妨a〉b
解两次方程比较大小 一个方程ax+by=k,另一个是bx+ay=k
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<math.h> using namespace std; __int64 xx, yy; __int64 exGcd(__int64 a,__int64 b) { if(b == 0) { xx = 1; yy = 0; return a; } __int64 r = exGcd(b, a % b); __int64 t = xx; xx = yy; yy = t - a / b * yy; return r; } int main() { __int64 x,y,X,Y,a,b,di,maxn1,maxn2; while(scanf("%I64d%I64d%I64d",&a,&b,&di)!=EOF) { if(a==0&&b==0&&di==0) break; __int64 d=exGcd(a,b); X=di/d*xx%b+b; X%=(b/d); Y=abs(di-a*X)/b; Y=abs(Y); maxn1=X+Y; maxn2=a*X+b*Y; d=exGcd(b,a); x=di/d*xx%a+a; x%=(a/d); y=abs(di-b*x)/a; y=abs(y); if(maxn1>x+y) { X=y; Y=x; } else if((maxn1==x+y)&&(maxn2>b*x+a*y)) { X=y; Y=x; } cout<<X<<" "<<Y<<endl; } // system("PAUSE"); return 0; }
poj1006 解线性同余方程
方程组为:
x= p(mod 23)
x=e(mod 28)
x=i(mod 33)
由于已知了23,28,33我们可以手算,将逆求出来,利用中国剩余定理的解法就能解出来
#include<iostream> using namespace std; int main() { int a,b,c,d; int n(0); while(cin>>a>>b>>c>>d) { n++; if(a==-1&&b==-1&&c==-1&&d==-1)break; int i; i=(5544*a+14421*b+1288*c-d)%(23*28*33); if(i<=0)cout<<"Case "<<n<<": the next triple peak occurs in "<<21252-d<<" days.\n"; else cout<<"Case "<<n<<": the next triple peak occurs in "<<i<<" days.\n"; } return 0; }
我们也可以用扩展欧几里得来求逆,或者直接暴力,下面是直接暴力的代码
#include<iostream> #include<cstdlib> #include<stdio.h> #include<cmath> using namespace std; int p,e,I,d; int m[4],M,f[4],g[4],b[4]; int count; int main() { m[0]=23,m[1]=28,m[2]=33; count=1; while(scanf("%d%d%d%d",&p,&e,&I,&d)!=EOF) { if(p==-1&&e==-1&&I==-1&&d==-1) break; b[0]=p,b[1]=e,b[2]=I; int M=1; for(int i=0;i<3;i++) M=M*m[i]; for(int i=0;i<3;i++) f[i]=M/m[i]; for(int i=0;i<3;i++) { int j=1; while((f[i]*j)%m[i]!=1)//用循环计算y[i]应该是整个程序中最烂的算法 j++; g[i]=j; } /*for(int i=0;i<3;i++) cout<<g[i]<<endl;*/ int x; x=0; for(int i=0;i<3;i++) x+=g[i]*f[i]*b[i]; x=x%M; x=x-d; if(x<=0) x+=21252; printf("Case %d: the next triple peak occurs in %d days.\n",count++,x); } }
fzu 1402Problem 1402 猪的安家
Accept: 647 Submit: 4558
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Andy和Mary养了很多猪。他们想要给猪安家。但是Andy没有足够的猪圈,很多猪只能够在一个猪圈安家。举个例子,假如有16头猪,Andy建了3个猪圈,为了保证公平,剩下1头猪就没有地方安家了。Mary生气了,骂Andy没有脑子,并让他重新建立猪圈。这回Andy建造了5个猪圈,但是仍然有1头猪没有地方去,然后Andy又建造了7个猪圈,但是还有2头没有地方去。Andy都快疯了。你对这个事情感兴趣起来,你想通过Andy建造猪圈的过程,知道Andy家至少养了多少头猪。
Input
输入包含多组测试数据。每组数据第一行包含一个整数n (n <= 10)–Andy建立猪圈的次数,解下来n行,每行两个整数ai, bi( bi <= ai <= 1000),表示Andy建立了ai个猪圈,有bi头猪没有去处。你可以假定(ai, aj) = 1.
Output
输出包含一个正整数,即为Andy家至少养猪的数目。
Sample Input
3
3 1
5 1
7 2
Sample Output
16
典型的利用中国剩余定理求解线性方程组的题。
根据题意我们设有x只猪,则有方程组:
x=b1 mod a1
x=b2 mod a2
x=b3 mod a3
……
x=bi mod ai
题中说了ai是两两互质的,所以我们可以直接利用中国剩余定理解题。
那么题中的解为x=M1'M1b1+M2'M2b2……+Mk'MKbk(mod m) m=a1*a2*a3……ai
Mi'Mi= 1(mod mi) 即Mi'Mi+mi*y=1求逆用扩展欧几里得解出Mi'
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef __int64 int64; int64 a[15],b[15]; int64 Extend_Euclid(int64 a, int64 b, int64&x, int64& y) { if(b==0) { x=1,y=0; return a; } int64 d = Extend_Euclid(b,a%b,x,y); int64 t = x; x = y; y = t - a/b*y; return d; } //求解模线性方程组x=ai(mod ni) int64 China_Reminder(int len, int64* a, int64* n) { int i; int64 N = 1; int64 result = 0; for(i = 0; i < len; i++) N = N*n[i]; for(i = 0; i < len; i++) { int64 m = N/n[i]; int64 x,y; Extend_Euclid(m,n[i],x,y); x = (x%n[i]+n[i])%n[i]; result = (result + m*a[i]*x%N)%N; } return result; } int main() { int n; while(scanf("%d",&n)!=EOF) { for(int i = 0; i < n; i++) scanf("%I64d %I64d",&a[i],&b[i]); printf("%I64d\n",China_Reminder(n,b,a)); } return 0; }
Poj2891解线性同余方程,判有没有解
除数 余数
2
8 7
11 9
输出
31
方程组
x= a1(mod b1)
x=a2 (mod b2)
……
x=ai(mod bi)
不能利用中国剩余定理解,因为b1,b2……bi不一定两两互素
#include <cstdlib> #include <iostream> #include <stdio.h> using namespace std; long long extgcd(long long a,long long b,long long &x,long long &y){ if (b == 0) { x=1; y=0; return a; } long long d = extgcd(b, a % b, x, y); long long t = x; x = y; y = t - a / b * y; return d; } int main() { long long n,k,m,a,r; bool flag=1; while(scanf("%lld",&n)!=-1) { flag=1; if(n==0) {printf("-1\n");continue;} scanf("%lld%lld",&k,&m); while(--n) { scanf("%lld %lld",&a,&r); if(flag) { // printf("%I64d %I64d ",k,m); long long x,y; long long d=extgcd(k,a,x,y); if((r-m)%d) {flag=0;continue;} x=(x*(r-m)/d+a/d)%(a/d); long long side=k/d*a; m=((x*k+m)%side)%side; if(m<0) m+=side; k=side; /*kx+m=M ax+r=M 联立得: kx-ax=r-m 更新k为LCM(k,a)------>side=k/d*a;d为gcd(k,a); m为求得的M*/ } } if(!flag) printf("-1\n"); else printf("%lld\n",m); } }
hdu1573
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1926 Accepted Submission(s): 573
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
1 0 3
#include <cstdlib> #include <iostream> #include <stdio.h> using namespace std; long long extgcd(long long a,long long b,long long &x,long long &y) { if (b == 0) { x=1; y=0; return a; } long long d = extgcd(b, a % b, x, y); long long t = x; x = y; y = t - a / b * y; return d; } int main() { long long n,t,mi,a[22],r[22]; bool flag; scanf("%I64d",&t); while(t--) { scanf("%I64d%I64d",&n,&mi); flag=true; for(long long i=0;i<mi;i++) scanf("%I64d",&a[i]); for(long long i=0;i<mi;i++) scanf("%I64d",&r[i]); long long m,k; k=a[0];m=r[0]; long long side; for(long long i=1;i<mi;i++) { if(flag) { long long x,y; long long d=extgcd(k,a[i],x,y); if((r[i]-m)%d) {flag=false;break;} x=(x*(r[i]-m)/d+a[i]/d)%(a[i]/d); // x*=(r[i]-m)/d; // m=m+k*x; side=k/d*a[i]; m=((x*k+m)%side)%side; while(m<0) m+=side; m%=side; k=side; /*kx+m=M ax+r=M 联立得: kx-ax=r-m 更新k为LCM(k,a)------>side=k/d*a;d为gcd(k,a); m为求得的M*/ } } while(m<0) m+=k; m%=k; if(!flag||m>n) puts("0"); else { long long res=(n-m)/k+1; if(m==0) res--; printf("%lld\n",res); } } }