-中国剩余定理介绍
定理1:两个公差互质的等差数列的交为一个新的等差数列,并且该等差数列的公差为原来两个公差的乘积。
{x≡a(mod m1)x≡b(mod m2)
x≡x0(mod m1m2)
解决的问题:一元线性同余方程组(其中 gcd(mi,mj)=1 | i!=j )
⎧⎩⎨⎪⎪⎪⎪x≡a1(mod m1)x≡a2(mod m2)......x≡an(mod mn)
解法:
令
M=∏i∈[1,n]mi
Mi=∏i∈[1,n]mimi
TiMi≡1(mod mi)
则有通解:
∑i∈[1,n]aiTiMi + kM | k∈ℤ
分析:
令
0≡x(mod 7)
的所有
x
为集合
令
ai≡x(mod pi) and 0≡x(mod 7)
的所有
x
为集合
答案就是:
S−A1∪A2∪A3...
后面的集合并,显然用容斥原理来做,中间求CRT的时候乘法要爆long long,所以用快速乘法。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define pr(x) cout << #x << ": " << x << " "
#define pl(x) cout << #x << ": " << x << endl;
struct jibancanyang
{
long long n, l, r, P[20], A[20];
long long m[20], mod[20], cnt;
long long extgcd(long long a, long long b, long long &x, long long &y) {
long long d = a;
if (b) d = extgcd(b, a % b, y, x), y -= a / b * x;
else x = 1, y = 0;
return d;
}
long long mult(long long a, long long k, long long m) {
long long ret = 0;
while (k) {
if (k & 1) ret = (ret + a) % m;
a = (a + a) % m;
k >>= 1;
}
return ret;
}
long long crt(long long r) {
long long M = 1, ans = 0;
for (int i = 0; i < cnt; ++i)
M *= m[i];
for (int i = 0; i < cnt; ++i) {
long long N = M / m[i];
long long x, y;
extgcd(N, m[i], x, y);
x = (x % m[i] + m[i]) % m[i];
ans = (ans + mult(mult(mod[i] , x, M), N, M)) % M;
}
return (r - ans + M) / M;
}
long long run(long long x) {
long long ret = x / 7;
m[0] = 7, mod[0] = 0;
for (int i = 1; i < (1 << n); ++i) {
cnt = 1;
for (int j = 0; j != n; ++j) {
if ((i >> j) & 1) m[cnt] = P[j], mod[cnt++] = A[j];
}
long long c = crt(x);
cnt & 1 ? ret += c : ret -= c;
}
return ret;
}
void fun() {
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; ++cas) {
scanf("%lld%lld%lld", &n, &l, &r);
for (int i = 0; i != n; ++i)
scanf("%lld%lld", &P[i], &A[i]);
printf("Case #%d: %lld\n", cas, run(r) - run(l - 1));
}
}
}ac;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
ac.fun();
return 0;
}