您的位置:首页 > 其它

HDU-5768-Lucky7(中国剩余定理+容斥)

2016-07-30 11:00 477 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768

题意:求[a,b]区间内能被7整除且不满足x%pi=ai(1<=i<=n)的数有多少个;

题解:

因为满足任意一组pi和ai,即可使一个“幸运数”被“污染”,我们可以想到通过容斥来处理这个问题。当我们选定了一系列pi和ai后,题意转化为求[x,y]中被7整除余0,且被这一系列pi除余ai的数的个数,可以看成若干个同余方程联立成的一次同余方程组。然后我们就可以很自然而然的想到了中国剩余定理。需要注意的是,在处理中国剩余定理的过程中,可能会发生超出LongLong的情况,需要写个类似于快速幂的快速乘法来处理。

#include <bits/stdc++.h>
using namespace std;
//#define mod 1000000007
long long quick_mul(long long a, long long b,long long mod)
{
long long ans=0;
while(b)
{
if(b&1)ans=(ans+a)%mod;
b>>=1;
a=(a+a)%mod;
}
return ans;
}
long long extend_Euclid(long long a, long long b, long long &x, long long &y)
{
if(b==0){x = 1;y = 0;return a;}
long long r = extend_Euclid(b, a%b, y, x);
y -= a/b*x;
return r;
}
#define bug cout<<"bug"<<endl
#define INF 0x3f3f3f3f
const int MAXN = 107;
long long mo[MAXN],er[MAXN];
int vis[MAXN];
long long China(int n)
{
long long M = 1, ans = 0;
for (int i = 0; i <= n; ++i)if(vis[i])
M *= mo[i];
for(int i = 0; i <= n; i++)if(vis[i])
{
long long N = M/mo[i];
long long x, y;
extend_Euclid(N, mo[i], x, y);
x = (x%mo[i]+mo[i])%mo[i];
ans = ((ans+quick_mul(quick_mul(er[i],N,M), x, M))%M + M) % M;
}
return ans;
}
int main()
{
int T,n,cas=1;;
long long a,b;
scanf("%d",&T);
while(T--)
{
scanf("%d%I64d%I64d",&n,&a,&b);
for(int i=0; i<n; ++i)
scanf("%I64d%I64d",&mo[i],&er[i]);
mo
=7,er
=0;
vis
=1;
long long l7=7;
long long ans=0;
int temp=1<<n;
for(int i=0; i<temp; ++i)
{
int k=i,flag=0;
long long all=7,poi;
for(int j=0; j<n; ++j)
{
vis[j]=k&1;
k>>=1;
flag+=vis[j];
if(vis[j])all*=mo[j];
}
long long c=China(n);
if(c>a)c-=((c-a)/all)*all;
if(c<a)c+=((a-c)/all)*all;
if(c<a)c+=all;
if(c<=b)poi=(b-c)/all+1;
else poi=0;
if(flag&1)ans-=poi;
else ans+=poi;
}
printf("Case #%d: %I64d\n",cas++,ans);
}
}

/*
4
2 1 100
3 2
5 3
0 1 100
0 1 1
0 7 7
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: