中国剩余定理的模板题
只是有一个问题就是求出来X=k*M+R中的R比给定的日期还大,但是如果负数的整除就不是向下取整了,为了解决这个问题,我们将R减小M,这样总是正的,求出来的就没有什么问题。
#include <iostream>
#include<cstdio>
using namespace std;
#include <algorithm>
#include <string>
#include <stack>
#include <cmath>
#define LL long long
#define _for(i,j,k) for(int i=j;i<=k;i++)const int maxn = 1e5+5;typedef long long ll; int m[4]={0,23,28,33};
int r[4];void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)
{if(!b) {d=a; x=1; y=0;}else{ex_gcd(b,a%b,d,y,x); y-=(a/b)*x;}
}ll gcd(ll a,ll b)
{return b==0?a:gcd(b,a%b);
}bool mod_equation(ll n,ll& M,ll& R)
{M=1; ll t,d,k,x=0;for(int i=1;i<=n;i++) M=M*m[i];for(int i=1;i<=n;i++){ex_gcd(M/m[i],m[i],d,t,k);t=(t%m[i]+m[i])%m[i];x=(x+t*M/m[i]*r[i])%M;}R=(x%M+M)%M;return true;
}int main()
{int begin;int Case=0;while(~scanf("%d%d%d%d",&r[1],&r[2],&r[3],&begin)){ll M,R;int n=3;if(r[1]==-1 && r[2]==-1 && r[3]==-1 && begin==-1)break;++Case;mod_equation(3,M,R);//printf("M=%lld R=%lld\n",M,R);R-=M;int k=(begin-R)/M+1;//printf("k=%d\n",k);printf("Case %d: the next triple peak occurs in %lld days.\n",Case,k*M+R-begin);}return 0;
}
又写了一个中国剩余定理版的,巨短。。(那些奇怪的数字是求的逆元)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<map>
#include<queue>
#include<set>
#include<vector>using namespace std;typedef long long ll;
const int MAXN=1e5+5;int a,b,c,d;
int M=23*28*33;int main()
{int Case=0;while(~scanf("%d%d%d%d",&a,&b,&c,&d)){if(a==-1 && b==-1 && c==-1 && d==-1) break;Case++;int ans=a*M/23*6+b*M/28*19+c*M/33*2;ans%=M;ans-=M;//ans+kM>d kM>d-ans k>(d-ans)/Mint k=(d-ans)/M+1;printf("Case %d: the next triple peak occurs in %d days.\n",Case,k*M+ans-d);}return 0;
}