Problem I. Count HDU - 6434(欧拉函数)

Problem I. Count HDU - 6434

 Multiple query, for each n, you need to get
n i-1
∑ ∑ [gcd(i + j, i - j) = 1]
i=1 j=1 

Input
On the first line, there is a positive integer T, which describe the number of queries. Next there are T lines, each line give a positive integer n, as mentioned above.
T<=1e5, n<=2e7
Output
Your output should include T lines, for each line, output the answer for the corre- sponding n.
Sample Input

4
978
438
233
666

Sample Output

194041
38951
11065
89963

题意:

求上述公式

i = 1 n j = 1 i 1 [ g c d ( i + j , i j ) == 1 ]

思路:

在求解 a n s n i c h e c k g c d ( a , b ) 1 a b 是否互质

也就 i a + b = 2 i a b

这时我们需要一个规律: a b a b a + b a b 2 i ,这样的话我们求满足 i g c d = 1 对数的时候,只要求 ϕ ( 2 i ) 2 a n s 的话 就是求前缀和

证明: a b a b a + b 互质 :
先假设 a ( a + b ) g c d = t a = t x , ( a + b ) = t y
那么 b = t y t x = t ( y x ) , a b t a ( a + b )
同理可证 b

注意使用线性求欧拉函数和素数的方法,否则会超时。

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e7+7;
const int maxd = 2e7+7;
const int mod = 998244353;
int phi[maxn],prim[maxn];
ll sum[maxn];
void init(){
    memset(phi,0,sizeof(phi));
    phi[1] = 1;
    int id = 0;
    for(int i = 2; i < maxn; i++){
        if(!phi[i]){
            phi[i] = i - 1;
            prim[id++] = i;
        }
        for(int j = 0; j < id && prim[j] * i < maxn; j++){
            if(i % prim[j]){
                phi[i*prim[j]] = phi[i] * (prim[j] - 1);
            }
            else{
                phi[i*prim[j]] = phi[i] * prim[j];
                break;
            }
        }
    }
    sum[1] = 0;
    for(int i = 2; i < maxd; i++){
        sum[i] = phi[i*2] / 2;
        sum[i] += sum[i-1];
    }
}
int main(){
    init();
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        printf("%lld\n",sum[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/82115804