中國剩餘定理(互質+非互質)
阿新 • • 發佈:2019-02-18
給定n組同餘方程,求x。
……
若
mi 兩兩互素,則x必定有解。令
M=m1∗m2∗...∗mn
x=(a1M1M−1+a2M2M−2+...+anMnM−n)mod M 其中
Mi=M/mi ,
M−i 為Mi modmi 的逆。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int n;
int a[15], m[15];
void ex_gcd(int a, int b, int &x, int &y)
{
if(!b)
{
x = 1;
y = 0;
}
else
{
ex_gcd(b, a%b, y, x);
y -= (a / b) * x;
}
}
LL CRT(int a[], int m[])
{
LL M = 1;
LL ans = 0;
for(int i = 0; i < n; i++)
M *= m[i];
for(int i = 0 ; i < n; i++)
{
LL t = M / m[i];
int x, y;
ex_gcd(t, m[i], x, y);
ans += a[i] * t * x;
ans %= M;
}
ans = (ans + M) % M;
return ans;
}
int main(int argc, char const *argv[])
{
cin >> n;
for(int i = 0; i < n; i++)
cin >> m[i] >> a[i];
cout << CRT(a, m);
return 0;
}
若
mi 非互質對前兩個方程
x≡a1(mod m1)
x≡a2(mod m2) 有
m1∗y1−m2∗y2=a2−a1 解出最小
y1 ,x=a1+m1∗y1
兩個方程可以合成為y≡x(mod lcm(m1,m2))
一隻合併下去,就可以得到最終結果。
若方程無解,無法合併,則最終無解。對於題目所給正整數的要求,只有一種反例,就是結果輸出為0的情況,
這個可以特殊考慮,只需要考慮所有數的最小公倍數即可。
//hdu 5668 circle
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int c[25], vis[25], a[25], m[25];
void ex_gcd(int a, int b, int &d, int &x, int &y)
{
if(!b)
{
d = a;
x = 1;
y = 0;
}
else
{
ex_gcd(b, a%b, d, y, x);
y -= (a / b) * x;
}
}
int CRT(int n)
{
int c = a[1], l = m[1];
int d, x, y;
for(int i = 2; i <= n; i++)
{
ex_gcd(l, m[i], d, x, y);
if((a[i]-c)%d)
return -1;
int tt = m[i] / d;
x = (a[i] - c) / d * x % (m[i] / d);
c += l * x;
l = l / d * m[i];
c %= l;
}
return (c + l) % l ? (c + l) % l : l;
}
int main(int argc, char const *argv[])
{
int t;
cin >> t;
while(t--)
{
int tmp, n;
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> tmp;
c[tmp] = i;
}
memset(vis, 0, sizeof(vis));
int j = 0;
for(int i = 1; i <= n; i++)
{
int k = 0;
while(j != c[i])
{
j++;
if(j > n)
j = 1;
if(!vis[j])
k++;
}
vis[c[i]] = 1;
a[i] = k;
m[i] = n - i + 1;
a[i] %= m[i];
}
int ans = CRT(n);
if(ans != -1)
printf("%d\n", ans);
else
printf("Creation August is a SB!\n");
}
return 0;
}