您的位置:首页 > 其它

HDU 5768 Lucky7 中国剩余定理

2016-07-29 19:50 302 查看
转载声明:http://blog.csdn.net/acdreamers/article/details/8050018 (模板)

题意:给你一段区间的,要求能被7整除的个数,然后给你n个条件, 其中的得到所有数不能满足 给出的 x%x1=r1, x%x2=r2。。。等条件.输出个数.

个人感想:

这是一道中国剩余定理题目, 我当时比赛的时候我也不会做..我只是知道有这样的公式..就是可以求出满足的所有解,但我不知道是什么鬼..然后大牛告诉我了是中国剩余定理.我特么就半桶水的东西,我感觉怎么也不会考…然后之前都没学下去,真是瞎鸡巴搞了. 我是知道要用到容斥,算了..不说心酸史, 我直接套上链接的模板去做的,在统计区间中整数的数组的时候要注意 最左区间要-1, 和求那个前缀和一样,否则就除问题了,我坑了一个多小时在那.默哀.. 例如 求 7<= 7t<=9;满足的条件中 t的个数, 这时候答案是0的! 因为是向下取整导致这样的问题,所以求t时 应该 7-1<7t<=9 这样才求出来是1! 而且要注意 t能满足0的情况,这样的区间相减是不包括0的!!

/* Author:GavinjouElephant
* Title:
* Number:
* main meanning:
*
*
*
*/

//#define OUT
#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define Clear(x) memset(x,0,sizeof(x))
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=20;
LL n,x,y;
int T;
LL a[maxn],p[maxn];
LL gcd(LL a,LL b)
{
return b? gcd(b, a % b) : a;
}

void extend_Euclid(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
extend_Euclid(b, a % b, x, y);
LL tmp = x;
x = y;
y = tmp - (a / b) * y;
}

LL Inv(LL a, LL b)
{
LL d = gcd(a, b);
if(d != 1) return -1;
LL x, y;
extend_Euclid(a, b, x, y);
return (x % b + b) % b;
}

bool Merge(LL a1, LL m1, LL a2, LL m2, LL &a3, LL &m3)
{
LL d = gcd(m1, m2);
LL c = a2 - a1;
if(c % d) return false;
c = (c % m2 + m2) % m2;
m1 /= d;
m2 /= d;
c /= d;
c *= Inv(m1, m2);
c %= m2;
c *= m1 * d;
c += a1;
m3 = m1 * m2 * d;
a3 = (c % m3 + m3) % m3;
return true;
}
LL solve(int n)
{
LL a1 = 0;
LL m1 = 7;
int tmp=0;

while(n)
{
if(n&1)
{
LL a2 = a[tmp];
LL m2 = p[tmp];
LL m3, a3;
if(!Merge(a1, m1, a2, m2, a3, m3))
return -1;
a1 = a3;
m1 = m3;
}
tmp++;
n>>=1;
}

a1=(a1 % m1 + m1) % m1;
LL res=0;

res+=((y-a1)/m1 -(x-a1-1)/m1);

if(a1>=x&&a1<=y)res++;//至于为什么要特殊判断 主要我们求出来的时候是( x<=a1+mt<=y,那么两边互相消去之后的t的个数是不包括0的,所以要特判一下.

return res;

}
LL getT(int n)
{
int res=0;
while(n)
{
if(n&1)res++;
n>>=1;
}
return res;
}
LL f(LL x)
{
if(x%2)return 1;
return -1;
}
int main()
{
#ifdef OUT
freopen("coco.txt","r",stdin);
freopen("lala.txt","w",stdout);
#endif
scanf("%d",&T);
for(int cas=1; cas<=T; cas++)
{
scanf("%I64d%I64d%I64d",&n,&x,&y);
LL ans=(y/7-(x-1)/7);

for(int i=0; i<n; i++)
{
scanf("%I64d%I64d",&p[i],&a[i]);
}
LL tmp=0;
LL limited=1<<n;

for(int i=1; i<limited; i++)
{
int tot=getT(i);

LL t=solve(i);
tmp+=f(tot)*t;
}
printf("Case #%d: %I64d\n",cas,ans-tmp);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: