hdu5768Lucky7

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768

题意:求在l~r中有多少个数x满足要求,要求:x%7=0,并且有n个p,a满足x%p=a。

分析:容斥+中国剩余定理。注意剩余定理里面可能爆longlong要用快速乘。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=100010;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const int MAX=1000000010;
const ll INF=1ll<<55;
const double pi=acos(-1.0);
typedef double db;
typedef unsigned long long ull;
ll a[20],p[20],X[20],Y[20];
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y) {
    if (!b) { d=a;x=1;y=0; }
    else { ex_gcd(b,a%b,d,y,x);y-=x*(a/b); }
}
ll inv(ll a,ll n) {
    ll d,x,y;
    ex_gcd(a,n,d,x,y);
    return d==1 ? (x+n)%n:-1;
}
ll mul(ll a,ll b,ll M) {
    ll ret=0;
    while (b) {
        if (b&1) ret=(ret+a)%M;
        a=(a+a)%M;b>>=1;
    }
    return (ret+M)%M;
}
ll CRT1(int n,ll *a,ll *m) {
    ll M=1,d,y,z,x=0;
    for (int i=0;i<n;i++) M*=m[i];
    for (int i=0;i<n;i++) {
        z=M/m[i];
        ex_gcd(m[i],z,d,d,y);
        x=(x+mul(mul(y,z,M),a[i],M))%M;
    }
    x=(x+M)%M;
    return x==0 ? M:x;
}
ll get(int x,int n,ll sum) {
    int i,k=1;
    ll M=1,CRT;
    for (i=0;i<20;i++)
    if (x&(1<<i)) { X[k]=p[i];Y[k]=a[i];k++; }
    for (i=0;i<k;i++) M*=X[i];
    CRT=CRT1(k,Y,X);
    if ((k-1)&1) return -(sum/M+(sum%M>=CRT));
    else return sum/M+(sum%M>=CRT);
}
int main()
{
    int i,n,t,ca;
    ll x,y,ans;
    scanf("%d", &t);
    X[0]=7;Y[0]=0;
    for (ca=1;ca<=t;ca++) {
        scanf("%d%I64d%I64d", &n, &x, &y);
        for (i=0;i<n;i++) scanf("%I64d%I64d", &p[i], &a[i]);
        for (ans=0,i=0;i<(1<<n);i++) ans+=get(i,n,y)-get(i,n,x-1);
        printf("Case #%d: %I64d\n", ca, ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值