您的位置:首页 > 其它

HDU5768 Lucky7

2016-07-29 09:07 204 查看
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5768

【题意】有n对数(p1,r1),(p2,r2),......,(pn,rn).求在给定的x,y闭区间中有几个数是7的倍数,同时任意数x%pi!=ri。

【分析】先求出7的倍数的数目,然后dfs容斥删除对pi取模等于ri的数的个数。删除的时候利用中国剩余定理求出满足条件的最小数X,每次增大所有数的积P。对于x≤X+n*P≤y,求非负整数n的个数及为满足条件的数的个数。

【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
const int MOD = 1e9+7;
const int MAXN = 1000000;
int n,cnt=0;
LL a[20],m[20];
LL prime[20],yu[20];
LL ans = 0,tmp,d;
LL extend_gcd(LL a,LL b,LL &x,LL &y)
{
int t,ret;
if(!b)
{
x = 1;
y = 0;
return a;
}
ret=extend_gcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return ret;
}

void fun(LL a,LL b,LL n){
LL x,y;
d=extend_gcd(a,n,x,y);
tmp=(x*(b/d)%n+n)%n;
}
LL CRT()
{
LL a1=0,m1=7;
for(int i=1;i<cnt;i++){
fun(m1,yu[i]-a1,prime[i]);
a1+=m1*tmp;
m1=m1*prime[i]/d;
a1=(a1%m1+m1)%m1;
}
return a1;
}
void dfs(int p,long long x,long long y,int t)
{
if(cnt>1 && t==n){
long long X = CRT();
long long P = 7;
for(int i=1;i<cnt;++i)
P*=prime[i];
if(y >= X)
{
if(cnt%2 == 0)
{
if(x < X)
ans -= ((y-X) / P + 1);
else
ans -= (((y-X) / P) - ((x-X-1) / P));
}
else
{
if(x < X)
ans += ((y-X) / P + 1);
else
ans += ( ((y-X) / P) - ((x-X-1) / P) );
}
}
}
if(p>n)
return;
prime[cnt]=m[p];
yu[cnt++]=a[p];
dfs(p+1,x,y,t+1);
cnt--;
dfs(p+1,x,y,t+1);
}

int main()
{
int t;
long long x,y;
scanf("%d",&t);
for(int ica=1;ica<=t;ica++)
{
ans = 0;
cnt = 1;
cin>>n>>x>>y;
for(int i=1;i<=n;i++)
cin>>m[i]>>a[i];
ans+=(y / 7 - (x-1) / 7);
prime[0]=7;
yu[0]=0;
dfs(1,x,y,0);
printf("Case #%d: %I64d\n",ica,ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息