HDU - 6434 Problem I. Count 推导+欧拉函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiang_6/article/details/81951505

题意:(如下)

Multiple query, for each n, you need to get 


n      i-1 
∑     ∑ [gcd(i + j, i - j) = 1] 
i=1    j=1

思路:

在求解 ans_n 时,首先我们考虑小于 n 的 i, 我们要check 如题意满足的 gcd(a, b) 是否为1,也就是 a 跟 b 是否互质

也就是对于 i 我们要找满足  (a+b=2*i)&& (a b互质) 的对数,

这时我们需要一个规律:a与b互质,那么 a,b 分别与 (a+b)互质,这样的话我们求满足 i 的条件的对数的时候,只要求 phi[ 2*i ] (欧拉函数)  ÷   2  就好了,,求ans_n的话 就是求前缀和

证一下: 若a与b互质,那么 a,b 分别与 (a+b)互质 :

先假设 a 与 (a+b) 不互质,那么令他们的gcd = t,  a=t*x, (a+b) = t*y

那么 b = t*y - t*x = t * (y-x) ,这样 a,b就会有公因子 t ,矛盾,所以 a 与 (a+b) 互质

#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];
void get_ouler(int n) {
  memset(phi, 0, sizeof phi);
  phi[1] = 1;
  int id = 0;
  for(int i = 2; i < n; ++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;
      }
    }
  }
}

ll sum[maxn];
void init() {
  sum[1] = 0;
  for(int i = 2; i < maxd; ++i) {
    sum[i] = phi[i*2]/2;
    sum[i] += sum[i-1];
  }
}

int main() {
  get_ouler(maxn);
  init();
  int T; scanf("%d", &T);
  while(T--) {
    ll n; scanf("%lld", &n);
    printf("%lld\n", sum[n]);
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/xiang_6/article/details/81951505