题目
题意:
对于7的倍数是一个幸运数字,但是给出了n个m和a,如果说一个数x满足(x equiv a_i(mod m_i)),那就不是幸运数字
求([x,y])区间里幸运数字的个数
单考虑([x,y])里7的倍数,y / 7 - (x - 1) / 7
个
而对于n个条件,二进制枚举配合容斥,求出每个枚举的集合的CRT,但是,这CRT还得是7的倍数,那就用EXCRT,加入(xequiv 0(mod 7))这个条件即可
那么求出了最小正整数st,因为CRT是有一个周期(T = LCM(m_i))的,所以根据前缀和,求([1,n])满足(x = st + tT, tin Z^+)的数字个数,那么每次的容斥值就是cal(y) - cal(x - 1)
#include <iostream>
#include <cstdio>
#include <vector>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
void ex_gcd(ll a, ll b, ll &d, ll &x, ll &y){
if(b == 0){
d = a,x = 1,y = 0;
return;
}
ex_gcd(b, a%b, d, y, x);
y -= x * (a / b);
}
ll mull(ll a,ll b,ll mod){
ll ans = 0;
while(b){
if(b & 1)ans = (ans + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return ans;
}
ll ex_china(vector<ll> a, vector<ll> m, int n){//x = a(mod m)
ll M = m[0];
ll ans = a[0];
ll d, x, y;
for(int i = 1; i < n; i++){
ll c = ((a[i] - ans) % m[i] + m[i]) % m[i];
ex_gcd(M, m[i], d, x, y);
if(c % d)return -1;//不存在解的情况
ll mod = m[i] / d;
x = mull(x, c / d, mod);
ans += x * M;
M *= mod;
ans = (ans % M + M) % M;
}
return ans > 0?ans:ans + M;//注意ans是M倍数时输出M
}
ll GCD(ll a, ll b){
return b == 0 ? a : GCD(b, a % b);
}
ll LCM(ll a, ll b){
return a / GCD(a, b) * b;
}
ll cal(ll st, ll T, ll n){//[1, n]里
return (n - st) / T + (n >= st);
}
void solve(){//答案是[x, y]里7的倍数 - n个中国剩余定理
int n; ll x, y;
scanf("%d%lld%lld", &n, &x, &y);
ll a[16], m[16];
for(int i = 0; i < n; i++)
scanf("%lld%lld", &m[i], &a[i]);
ll ans = y / 7 - (x - 1) / 7;//[x, y]里7的倍数
ll ans1 = 0;
for(int i = 1; i < (1 << n); i++){//
int k = 0;
ll lcm = 1;
std::vector<ll> mm, aa;
for(int j = 0; j < n; j++){
if(i & (1 << j)){
k++; lcm = LCM(m[j], lcm);
mm.push_back(m[j]); aa.push_back(a[j]);
}
}
lcm = LCM(lcm, 7);
mm.push_back(7), aa.push_back(0);
ll chi = ex_china(aa, mm, k + 1);
chi = cal(chi, lcm, y) - cal(chi, lcm, x - 1);
if(k & 1)ans1 += chi;
else ans1 -= chi;
}
printf("%lld
", ans - ans1);
}
int main(){
int T;
scanf("%d", &T);
for(int tt = 1; tt <= T; tt++)
printf("Case #%d: ", tt), solve();
return 0;
}