GCD HUD 1695(容斥原理)

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

Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).

这题写的是与gcd有关但是,实际上做起来,没有关系,

实际上先看一组范围比如1到10的范围,然后k为2,那么1到10 里的数至少得是2的倍数,我们可以表示成num=2a,可以看a和2都是num的因子,而2a必须小于10,那么我们可以枚举a这个因子,这个a的上界就是10/2
枚举1到5就是相当与枚举了1到10并且是是可以整除k的数;
所有题目转化成求 1 b/k 1 d/k 1的合法可能

因为我们要求(x,y)和(y,x)是同一种,所假设x

所以应该s2+s3-s23

#include
#include
#include
#include 
#include
#include 
#include
#define N 100000
using namespace std;
vector<int> dit[100002];
bool pri[100002];
void prime()//这个用来枚举每个数的因子
{
    memset(pri,true,sizeof(pri));
    for(int i=2;i<=N;i++)
        if(pri[i])
        {
            for(int j=i;j<=N;j+=i)
            {
                pri[j]=false;
                dit[j].push_back(i);
            }
        }
}
int get(int limit,int state,int num)//state是一个2进制形式的状态,用来枚举这个数的因子组合
{
    int o=1;
    int count=0;
    for(int i=0;iif((1<//得出在state这个组合下的数
        }
    }
    int ans=limit/o;//那么这个就是在limit范围下的这个state集合的个数
    if(count%2==0)return -ans;//查看这个集合是多少个单个集合的交际,如果偶数就减去,反之加上
    else return ans;
}
int main()
{
    int b,d,k;
    int l;
    int n;
    prime();
    scanf("%d",&n);
    int t=1;
    while(n--)
    {
        scanf("%d%d%d%d%d",&l,&b,&l,&d,&k);
        if(!k)//特殊情况考虑
        {

            printf("Case %d: %d\n",t++,0);
            continue;
        }
        d/=k;
        b/=k;
        if(b>d)
        {
            int temp=b;
            b=d;
            d=temp;
        }
        int limit;
        long long ans=0;
        for(int i=1;i<=d;i++)
        {
            limit=min(i,b);
            ans+=limit;//加上总的,在由下面的枚举减去不合法的个数
            for(int s=1;s<(1<<(dit[i].size()));s++)
                ans-=get(limit,s,i);
        }
        printf("Case %d: %lld\n",t++,ans);
    }
    return 0;
}

你可能感兴趣的:(组合数学,容斥原理)