除数互质
void extgcd(int a,int b,int &x,int &y)
{
if(!b){x = 1,y = 0;}
else{extgcd(b,a%b,y,x); y -= (a/b)*x;}
}
int inv(int a,int n)
{
int x,y;
extgcd(a,n,x,y);
x = (x % n + n) % n;
return x;
}
int china()
{
int p = 1,ans = 0;
for(int i=0;i<n;i++) p *= m[i];
for(int i=0;i<n;i++){
int w = p / m[i];
ans = (ans + a[i] * w * inv(w,m[i])) % p;
}
return ans;
}
除数不互质
void extgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d = a,x = 1,y = 0;}
else{extgcd(b,a%b,d,y,x); y -= x*(a/b);}
}
ll China(){
ll a1 = a[1], n1 = n[1];
for(int i=2;i<=num;i++){
ll a2 = a[i], n2 = n[i];
ll c = a2 - a1;
ll k1,k2,d;
extgcd(n1,n2,d,k1,k2); //求解n1k1 - n2k2 = a2 - a1
if(c % d) return -1;
c /= d, n2 /= d;
k1 *= c;
k1 = (k1 % n2 + n2) % n2; //找出最小的整数解
a1 += n1 * k1;
n1 *= n2;
}
return a1;
}
/*防止溢出*/
__int128 China(){
__int128 a1 = a[1], n1 = n[1];
for(int i=2;i<=num;i++){
__int128 a2 = a[i], n2 = n[i];
__int128 c = a2 - a1;
__int128 k1,k2,d;
extgcd(n1,n2,d,k1,k2);
if(c % d) return -1;
k1 = ((k1 * c / d) % (n2 / d) + (n2 / d)) % (n2 / d);
a1 += n1 * k1;
n1 = n1 * n2 / d;
}
return a1;
}
HDU3579
题解:输出最小正整数
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int const N = 20;
ll a[N],n[N];
int num;
void extgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d = a,x = 1,y = 0;}
else{extgcd(b,a%b,d,y,x); y -= x*(a/b);}
}
ll China(){
ll a1 = a[1], n1 = n[1];
for(int i=2;i<=num;i++){
ll a2 = a[i], n2 = n[i];
ll c = a2 - a1;
ll k1,k2,d;
extgcd(n1,n2,d,k1,k2); //求解n1k1 - n2k2 = a2 - a1
if(c % d) return -1;
c /= d, n2 /= d;
k1 *= c;
k1 = (k1 % n2 + n2) % n2; //找出最小的整数解
a1 += n1 * k1;
n1 *= n2;
}
return a1 > 0 ? a1 : n1; //输出最小整数解,如果a1 = 0,那么a1 % n1还为0,所以a1 + n1.
}
int main(){
int T,caser = 0;
scanf("%d",&T);
while(T--){
scanf("%d",&num);
for(int i=1;i<=num;i++) scanf("%lld",&n[i]);
for(int i=1;i<=num;i++) scanf("%lld",&a[i]);
printf("Case %d: %lld\n",++caser,China());
}
return 0;
}
HDU1573
题解:输出≤n的个数
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int const N = 10 + 5;
ll a[N],n[N],high;
int num;
void extgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d = a, x = 1, y = 0;}
else{extgcd(b,a%b,d,y,x); y -= x*(a/b);}
}
ll solve(){
ll a1 = a[1], n1 = n[1];
for(int i=2;i<=num;i++){
ll a2 = a[i], n2 = n[i], c = a2 - a1;
ll k1,k2,d;
extgcd(n1,n2,d,k1,k2);
if(c % d) return 0;
n2 /= d, c /= d;
k1 *= c;
k1 = (k1 % n2 + n2) % n2;
a1 += k1 * n1;
n1 *= n2;
}
if(a1 > high) return 0;
else if(a1 == 0) return high / n1; //必须要正整数
else return (high - a1) / n1 + 1;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%lld%d",&high,&num);
for(int i=1;i<=num;i++) scanf("%lld",&n[i]);
for(int i=1;i<=num;i++) scanf("%lld",&a[i]);
printf("%lld\n",solve());
}
return 0;
}
POJ2891
题解:模板题
代码:
#include <algorithm>
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
typedef long long ll;
ll a1,a2,n1,n2;
int num;
void extgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d = a,x = 1,y = 0;}
else{extgcd(b,a%b,d,y,x); y -= a/b*x;}
}
int main(){
while(~scanf("%d",&num)){
bool flag = true;
scanf("%lld%lld",&n1,&a1);
for(int i=1;i<num;i++){
scanf("%lld%lld",&n2,&a2);
ll c = a2 - a1,k1,k2,d;
extgcd(n1,n2,d,k1,k2);
if(c % d) flag = 0;
n2 /= d, c /= d;
k1 *= c;
k1 = (k1 % n2 + n2) % n2;
a1 += n1 * k1;
n1 *= n2;
}
printf("%lld\n",flag ? a1 : -1);
}
return 0;
}
HDU1370
题解:还是模板题目,转换一下即可。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll const N = 21252;
ll a[5],n[5],m,d;
void extgcd(ll a,ll b,ll &x,ll &y){
if(!b){x = 1,y = 0;}
else{extgcd(b,a%b,y,x); y -= x*(a/b);}
}
ll inv(ll a,ll n){
ll x,y;
extgcd(a,n,x,y);
return (x % n + n) % n;
}
ll solve(){
ll ans = 0;
for(int i=1;i<=3;i++){
ll w = m / n[i];
ans = (ans + a[i] * w * inv(w,n[i])) % m;
}
return ans;
}
int main(){
n[1] = 23, n[2] = 28, n[3] = 33;
m = n[1] * n[2] * n[3];
int caser = 0,T;
scanf("%d",&T);
while(cin>>a[1]>>a[2]>>a[3]>>d && d != -1){
ll period = solve();
while(period <= d) period += m; //第一次重合可能≤起始日期,下一个triple day,所以即使这一次是也不可以。
printf("Case %d: the next triple peak occurs in %lld days.\n",++caser,period - d);
}
return 0;
}
HDU5668
题解:模拟一下。加入总共有n个人,一共数到K,现在统计的是第i个出局的人,从上一个出出局的人到这一个统计的个数为p。那么K % (n - i + 1) = p。每次出局一个做标记。这是一组除数为n - i + 1,余数为p的线性方程组。套模板。详情见代码。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int const N = 25;
int num[N],n,tmp,vis[N];
ll m[N],a[N];
void extgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d = a,x = 1, y = 0;}
else{extgcd(b,a % b,d,y,x); y -= x * (a/b);}
}
ll solve(){
ll a1 = a[1], n1 = m[1];
for(int i=2;i<=n;i++){
ll a2 = a[i], n2 = m[i], c = a2 - a1;
ll d,k1,k2;
extgcd(n1,n2,d,k1,k2);
if(c % d) return -1;
n2 /= d, c /= d;
k1 *= c;
k1 = (k1 % n2 + n2) % n2;
a1 += k1 * n1;
n1 *= n2;
}
return a1;
}
int main(){
int T;
cin>>T;
while(T--){
cin>>n;
memset(vis,true,sizeof(vis)); //表明在的人
for(int i=1;i<=n;i++){
cin>>tmp;
num[tmp] = i; //第tmp个出局的是第i个人
}
int j = 1; //现在是数到第j个人
for(int i=1;i<=n;i++){ //第i个出局的人
int k = 1; //统计余数
while(num[i] != j){
if(vis[j]) k++;
j = j % n + 1;
}
vis[num[i]] = false;
m[i] = (ll)(n - i + 1);
a[i] = (ll)k;
}
ll ans = solve();
if(ans == -1) printf("Creation August is a SB!\n");
else printf("%lld\n",ans);
}
}
HDU1930
题解:耐心看完题目,发现很简单。输出注意一下,最后的空格不能输出。否则PE。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int const N = 50 + 10;
int n;
char mp[N];
ll m[5],a[5],ans[N];
ll num;
void extgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d = a, x = 1, y = 0;}
else{extgcd(b,a%b,d,y,x); y -= x*(a/b);}
}
ll China(){
ll a1 = a[1], n1 = m[1];
for(int i=2;i<=4;i++){
ll a2 = a[i], n2 = m[i], c = a2 - a1;
ll k1,k2,d;
extgcd(n1,n2,d,k1,k2);
if(c % d) return 0;
n2 /= d, c /= d;
k1 *= c;
k1 = (k1 % n2 + n2) % n2;
a1 += k1 * n1;
n1 *= n2;
}
return a1;
}
int main(){
int T;
for(int i=1;i<=26;i++) mp[i] = i + 'A' - 1;
mp[27] = ' ';
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=4;i++) cin>>m[i];
for(int i=1;i<=n;i++){
cin>>num;
for(int k=4;k>=1;k--){
a[k] = num % 100;
num /= 100;
}
ans[i] = China();
}
for(int i=1;i<=n;i++){ //080527
string s;
s[2] = mp[ans[i] % 100], ans[i] /= 100;
s[1] = mp[ans[i] % 100], ans[i] /= 100;
s[0] = mp[ans[i]];
if(i != n) cout<<s[0]<<s[1]<<s[2];
else{
if(s[0] != ' ') cout<<s[0];
if(s[1] != ' ') cout<<s[1];
if(s[2] != ' ') cout<<s[2];
}
}
cout<<endl;
}
return 0;
}