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
题意:
求上述公式
思路:
在求解 ans时,首先我们考虑小于n的i,我们要check如题意满足的gcd(a,b)是否为1,也就是a跟b a n s 时 , 首 先 我 们 考 虑 小 于 n 的 i , 我 们 要 c h e c k 如 题 意 满 足 的 g c d ( a , b ) 是 否 为 1 , 也 就 是 a 跟 b 是否互质
也就 是对于i我们要找满足(a+b=2i)并且(ab互质)的对数, 是 对 于 i 我 们 要 找 满 足 ( a + b = 2 i ) 并 且 ( a b 互 质 ) 的 对 数 ,
这时我们需要一个规律: a与b互质,那么a,b分别与(a+b)互质,即a,b与2i互质 a 与 b 互 质 , 那 么 a , b 分 别 与 ( a + b ) 互 质 , 即 a , b 与 2 i 互 质 ,这样的话我们求满足 i条件下的gcd=1 i 条 件 下 的 g c d = 1 对数的时候,只要求 ϕ(2i)2就好了,求ans ϕ ( 2 i ) 2 就 好 了 , 求 a n s 的话 就是求前缀和
证明: 若a与b互质,那么a,b分别与(a+b) 若 a 与 b 互 质 , 那 么 a , b 分 别 与 ( a + b ) 互质 :
先假设 a与(a+b)不互质,那么令他们的gcd=t,a=t⋅x,(a+b)=t⋅y 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 = t ⋅ y − t ⋅ x = t ⋅ ( y − x ) , 这 样 a , b 就 会 有 公 因 子 t , 矛 盾 , 所 以 a 与 ( a + b ) 互 质
同理可证 b b <script type="math/tex" id="MathJax-Element-714">b</script>
注意使用线性求欧拉函数和素数的方法,否则会超时。
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;
}