Lucky7
题目链接
题目大意
被7整除的数被定义为幸运数,其中被 pi 模余 ai 的数不是幸运数,问从x到y总共有多少幸运数。
题解
中国剩余定理 容斥原理
明显要用中国剩余定理,不过重点在于只要一个数被
pi
模余
ai
,他就不是幸运数,注意到n很小,可以容斥解决,所以我们利用容斥先算出x,y之间能被7整除但不是幸运数的个数,最后用总数减掉就行了。
注意要用快速乘,会爆long long
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
#define maxn 20
using namespace std;
int T,n,p[maxn],a[maxn];
LL x,y;
LL extend_gcd(LL a,LL b,LL &x,LL &y)
{
LL ans;
if (b==0)
{
x=1;
y=0;
return a;
}
else ans=extend_gcd(b,a%b,x,y);
LL t=x;
x=y;
y=t-(a/b)*y;
}
LL multi(LL a,LL b,LL m) {
LL ans=0;
while(b) {
if(b&1) ans=(a+ans)%m;
a=(a*2)% m;
b>>=1;
}
return ans;
}
LL C_reminder(LL x,LL y,int n)
{
x=(x-1)/7; y/=7;
LL M=1,m,A[maxn],P[maxn],h,ans=0,cnt=0;
for (int i=1;i<(1<<n);i++)
{
M=1; cnt=0;
memset(A,0,sizeof(A));
memset(P,0,sizeof(P));
h=0;
for (int j=0;j<15;j++) if ((1<<j)&i)
{
M*=p[j+1];
P[h]=p[j+1];
A[h]=a[j+1];
h++;
}
for (int k=0;k<h;k++)
{
m=M/P[k];
LL x1,y1;
extend_gcd(m,P[k],x1,y1);
x1=(x1%P[k]+P[k])%P[k];
cnt=(cnt+multi(m*A[k]%M,x1,M))%M;
}
LL k,K;
extend_gcd(7,M,k,K);
k=multi(k,cnt,M);
k=(k%M+M)%M;
if (h&1) ans+=(y-k+M)/M - (x-k+M)/M;
else ans-=(y-k+M)/M - (x-k+M)/M ;
}
return ans;
}
int main()
{
int Case=1;
scanf("%d",&T);
while (T--)
{
memset(p,0,sizeof(p));
memset(a,0,sizeof(a));
scanf("%d%I64d%I64d",&n,&x,&y);
for (int i=1;i<=n;i++) scanf("%d%d",&p[i],&a[i]);
LL cnt=y/7-(x-1)/7;
if (n==0)
{
printf("Case #%d: %I64d\n",Case++,cnt);
continue ;
}
cnt-=C_reminder(x,y,n);
printf("Case #%d: %I64d\n",Case++,cnt);
}
return 0;
}