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=1nj=1i1[gcd(i+j,ij)==1] ∑ i = 1 n ∑ j = 1 i − 1 [ g c d ( i + j , i − j ) == 1 ]

思路:

在求解 ansnicheckgcd(a,b)1ab a n s 时 , 首 先 我 们 考 虑 小 于 n 的 i , 我 们 要 c h e c k 如 题 意 满 足 的 g c d ( a , b ) 是 否 为 1 , 也 就 是 a 跟 b 是否互质

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

这时我们需要一个规律: ababa+bab2i a 与 b 互 质 , 那 么 a , b 分 别 与 ( a + b ) 互 质 , 即 a , b 与 2 i 互 质 ,这样的话我们求满足 igcd=1 i 条 件 下 的 g c d = 1 对数的时候,只要求 ϕ(2i)2ans ϕ ( 2 i ) 2 就 好 了 , 求 a n s 的话 就是求前缀和

证明: ababa+b 若 a 与 b 互 质 , 那 么 a , b 分 别 与 ( a + b ) 互质 :
先假设 a(a+b)gcd=ta=tx,(a+b)=ty a 与 ( a + b ) 不 互 质 , 那 么 令 他 们 的 g c d = t , a = t ⋅ x , ( a + b ) = t ⋅ y
那么 b=tytx=t(yx),abta(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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值