HDU5768 Lucky7

本文介绍了一道编程题的解题思路,题目要求找出在给定区间内既是7的倍数又不满足特定模运算条件的数的数量。通过先计算7的倍数总数,再用深度优先搜索结合中国剩余定理排除不符合条件的数来求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目连接: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);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值