HDU1695 略微有坑的容斥

Description
Given 5 integers: a, b, c, d, k, you’re to find x in a…b, y in c…d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you’re only required to output the total number of different number pairs.
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.

Yoiu can assume that a = c = 1 in all test cases.
Input
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.
Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.
Output
For each test case, print the number of choices. Use the format in the example.
Sample Input
2
1 3 1 5 1
1 11014 1 14409 9
Sample Output
Case 1: 9
Case 2: 736427

这个题其实本身是很简单
因为要求gcd是k的个数有多少
有一个很简单的想法
你的数据除了存在公约数是k的都毫无意义
甚至都不能得到整数
就算得到了整数也和公约数是k的没有任何区别
因此把题目给的b和d直接除以k
求互质的数有多少个并且去一下重复的就行了

开头预处理一下每个数的因数
因为T有3000这么多
不预处理肯定炸

然后坑就来了
1.k可以为0
不存在最大公约数是0的数哎…
所以直接特判为0
2.dfs的时候要用GCD而不是像一个二缺一样的乘起来….
我这个二缺疯狂wa数十次…没错就是数十次
以后一定要记得
GCDGCDGCDGCDGCDGCDGCDGCD
3.我也不知道为什么开了几个有用的longlong就会wa全开longlong就能过就这样吧以后全都是long long

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<memory.h>
using namespace std;
long long yinshu[100001][10];
long long aa,bb,cc,dd,kk,big,sma;
long long he1[30];
long long he2[30];
long long gcd(long long a,long long b)
{
    long long q=a,w=b;
    long long tem;
    while(b)
    {
        tem=a%b;
        a=b;
        b=tem;
    }
    return (q*w)/a;
}
void dfs(long long zuobiao,long long ceng,long long zong,long long a)
{
    if(ceng>yinshu[a][9])return ;
    long long tem=gcd(zong,yinshu[a][zuobiao]);
    he1[ceng]+=sma/tem;
    he2[ceng]+=big/tem;
    for(long long b=zuobiao+1;b<=yinshu[a][9];b++)dfs(b,ceng+1,tem,a);
}
int main()
{
    for(long long a=2;a<=100000;a++)
    {
        long long su=0;
        long long yy=a;
        for(long long q=2;q*q<=yy;q++)
        {
            if(yy%q==0)
            {
                yinshu[a][++su]=q;
                while(yy%q==0)yy/=q;
            }
        }
        if(yy!=1)yinshu[a][++su]=yy;
        yinshu[a][9]=su;
    }
    long long T;
    cin>>T;
    long long uu=0;
    while(T--)
    {
        cin>>aa>>bb>>cc>>dd>>kk;
        if(kk==0)
        {
            printf("Case %d: 0\n",++uu);
            continue;
        }
        bb=bb/kk;
        dd=dd/kk;
        big=max(bb,dd);
        sma=min(bb,dd);
        long long sum=big*sma;
        long long xiaosum=sma*sma;
        for(long long a=2;a<=sma;a++)
        {
            memset(he1,0,sizeof(he1));
            memset(he2,0,sizeof(he2));
            for(long long b=1;b<=yinshu[a][9];b++)dfs(b,1,1,a);
            for(long long b=1;b<=yinshu[a][9];b++)
            {
                if(b%2)
                {
                    sum=sum-he2[b];
                    xiaosum=xiaosum-he1[b];
                }
                else
                {
                    sum=sum+he2[b];
                    xiaosum=xiaosum+he1[b];
                }
            }
        }
        xiaosum=(xiaosum-1)/2;
        sum=sum-xiaosum;
        printf("Case %lld: %lld\n",++uu,sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值