zoukankan      html  css  js  c++  java
  • Problem I. Count HDU

    题目:

    (sum_{i=1}^{n}{sum_{j=1}^{i-1}{[gcd(i+j,i-j)=1]}})
    数据范围:(Tleq 10^5,nleq 2*10^7)

    分析:

    一看数据范围这么大,基本上就要预处理,或者推公式求。
    其实如果找规律的话,也可以找出。下面讲一下如何推导。
    推导:
    (a=i-j),
    根据拓展欧几里得,有:

    (gcd(i+j,a)=gcd(2*i-a,a)=gcd(2*i,a))

    原式转化为:

    (sum_{i=1}^{n}{sum_{a=1}^{i-1}{[gcd(2*i,a)=1]}})

    因为是 (2*i),所以对 (i) 的奇偶性进行讨论。
    (i) 为偶数时,与 (i) 互质的数和 (2*i) 也互质,所以结果为 (varphi(i))
    (i) 为奇数时,只有与 (i) 互质的奇数才会和 2*i 互质,所以结果为 (varphi(i)/2)
    那么为什么(i) 为奇数时,与 (i) 互质的数是奇,偶成对出现的呢?
    证明如下:
    首先证明 如果【1】(gcd(a,b)=1),那么 (gcd(a,a-b)=1);
    反证法:
    假设存在数 (k!=1),使得 (gcd(a,a-b)=k),即 (k|(a-b))(k|a),所以 (k|b)
    所以 (gcd(a,b)=k),出现矛盾,即证。
    (以下可以忽略)
    通过这个性质还可以求出小于等于n且与n互质的数的和,如下:

    [ans=egin{cases} frac{varphi(n)*n}{2} & ngeq 2\ 1 & n=1 end{cases}]

    由性质【1】易证。
    所以当 (i) 为奇数时,如果 (j) 和它互质,若 (j) 为奇数,则 (i-j) 必为偶数;若 (j) 为偶数,则 (i-j) 必为奇数。
    所以奇数和偶数成对出现。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int N=2e7+5;
    vector<int>prime;
    bool vis[N];
    ll phi[N],sum[N];
    void euler()
    {
        phi[1]=1;
        for(int i=2;i<=N-5;i++)
        {
            if(!vis[i])
            {
                prime.pb(i);
                phi[i]=i-1;
            }
            for(int j=0;j<prime.size()&&i*prime[j]<=N-5;j++)
            {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                else
                    phi[i*prime[j]]=phi[i]*phi[prime[j]];
            }
        }
        for(int i=1;i<=N-5;i++)
        {
            if(i&1)
                sum[i]=sum[i-1]+phi[i]/2;
            else
                sum[i]=sum[i-1]+phi[i];
        }
    }
    int main()
    {
        int t,n;
        euler();
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            if(n<0)
                printf("0
    ");
            else
                printf("%lld
    ",sum[n]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    数据结构实现时的注意事项
    用编程解决生活中的问题
    用编程解决生活中的问题
    中英文对照 —— 生物学基本概念
    中英文对照 —— 生物学基本概念
    面向对象 —— 对类(class)的理解
    面向对象 —— 对类(class)的理解
    百家姓 —— 特别的姓氏与姓氏的由来
    百家姓 —— 特别的姓氏与姓氏的由来
    英文段子
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/12465756.html
Copyright © 2011-2022 走看看