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

题目:

\(\sum_{i=1}^{n}{\sum_{j=1}^{i-1}{[gcd(i+j,i-j)=1]}}\)
数据范围:\(T\leq 10^5,n\leq 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=\begin{cases} \frac{\varphi(n)*n}{2} & n\geq 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\n");
        else
            printf("%lld\n",sum[n]);
    }
    return 0;
}

posted @ 2020-03-11 21:50  xzx9  阅读(179)  评论(0编辑  收藏  举报