版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wu_tongtong/article/details/78915588
Problem 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

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).



分析:

题目有一个重要的条件:Yoiu can assume that a = c = 1 in all test cases.

因此题目要求的就是:
我们现在的问题就是,如何求解:

这样我们就可以解决这个问题了

写完了之后,跑出来的答案比Simple Output要大
注意到题面说:(a,b)视为一个无序数对

说白了就是规定:a<=b

这就引出了一个新的问题:去重

手玩了小数据之后,

发现重复只会出现在:两个元素的定义域重叠的这一部分

也就是说,如果我们计算的是:
那么答案中会包括:(x1,y1),(y1,x1)(其中gcd(x1,y1)=z 且x1!=y1)以及(z,z)

其中重复的元素有:ans/2

所以我们把答案更改一下:

tip

当d=0的时候,直接返回0

在计算的时候,我们有玄学的分块法

注意:

如果没有a=c=1的条件

那么答案的计算就相当于一个利用二维前缀和求矩阵答案

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long

using namespace std;

const int N=100005;
int sshu[N],tot=0,a,b,c,d,k;
ll mu[N];
bool no[N];

void make()
{
    mu[1]=1;
    memset(no,0,sizeof(no));
    for (int i=2;i<N;i++)
    {
        if (!no[i])
        {
            sshu[++tot]=i;
            mu[i]=-1;
        }
        for (int j=1;j<=tot&&i*sshu[j]<N;j++)
        {
            no[i*sshu[j]]=1;
            if (i%sshu[j]==0)
            {
                mu[i*sshu[j]]=0;
                break;
            }
            mu[i*sshu[j]]=-mu[i];
        }
    }

    for (int i=2;i<N;i++) mu[i]+=mu[i-1];
}

ll solve(int n,int m,int d)    //玄学的分块 
{
    int i,j;
    if (!n||!m||!d) return 0;
    n/=d; m/=d; int last; ll ans=0; for (int i=1;i<=min(n,m);i=last+1) { last=min(n/(n/i),m/(m/i));
        ans+=(mu[last]-mu[i-1])*(n/i)*(m/i);
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    make();
    for (int cas=1;cas<=T;cas++)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        a--; c--;
        printf("Case %d: ",cas);
        ll ans=solve(b,d,k)-solve(min(b,d),min(b,d),k)/2;
        printf("%lld\n",ans);
    }
    return 0;
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-a47e74522c.css" rel="stylesheet">
            </div>