时间: 2020-11-25|47次围观|0 条评论

题目链接

Problem Description Multiple query, for each n, you need to get $$$$$$ \sum_{i=1}^{n} \sum_{j=1}^{i-1}{ [gcd(i + j, i - 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 题意 给定n,求代数式的值 分析 $$$gcd(i+j,i-j)$$$在形式上不够直观,不好分析,根据$$$gcd$$$的性质转化把它转化为$$$gcd(2j,i-j)$$$,通过交换求和顺序,并把$$$i-j$$$视为整体,原式转化为

$$$$$$ \begin{align} \text{原式}&= \sum_{i=1}^{n} \sum_{j=1}^{i-1}{ [gcd(i + j, i - j) = 1]}\\ &= \sum_{i=1}^{n} \sum_{j=1}^{i-1}{[gcd(2j, i - j) = 1]}\\ &= \sum_{j=1}^{n-1} \sum_{i=j+1}^{n}{[gcd(2j, i-j) = 1]}\\ &= \sum_{j=1}^{n-1} \sum_{i=1}^{j-1}{[gcd(2j, i) = 1]} \end{align} $$$$$$

注意到$$$\sum_{j=1}^{n-1} \sum_{i=1}^{j-1}$$$其实是在二维平面上三角形的区域内求和,于是进一步改写为:

$$$$$$ \sum_{i,j}^{i+j\le n}{[gcd(2j, i) = 1]} $$$$$$

$$$$$$ \begin{align} \text{令: }& f(n)=\sum_{i,j}^{i+j\le n}{[gcd(2j, i) = 1]}\\ & g(n)=f(n)-f(n-1)=\sum_{i,j}^{i+j=n}{[gcd(2j, i) = 1]} \end{align} $$$$$$ 注意到当$$$i+j=n$$$时,代入$$$j=n-i$$$,可以消掉$$$j$$$,并利用gcd的性质,可以进一步简化$$$g(n)$$$:

$$$$$$ \begin{align} g(n)&=\sum_{i=1}^{n-1}{[gcd(2n-2i, i) = 1]}\\ &=\sum_{i=1}^{n-1}{[gcd(2n, i) = 1]} \end{align} $$$$$$

所以接下来的问题就是,求$$$[1, n-1]$$$内,与$$$2n$$$互质的数有多少个。

这个问题可以继续简化,假设在$$$[1,n-1]$$$范围内,有$$$a_1,a_2,a_3,...a_p$$$与$$$2n$$$互质,那么根据gcd的性质,在$$$[n, 2n-1]$$$的范围内,相应的有$$$2n-a_1,2n-a_2,2n-a_3,...,2n-a_p$$$与$$$2n$$$互质。也就是说,两个范围内与$$$2n$$$互质的数是一样多的,所以结果很简单$$$g(n)$$$就是$$$\varphi(2n)$$$的一半,$$$g(n)=\varphi(2n)/2$$$。

$$$g(n)$$$已经不能再化简了,接下来再来看$$$f(n)$$$就容易多了,根据$$$f(n)$$$的递推式$$$g(n)=f(n)-f(n-1)$$$,很容易发现 $$$$$$ \begin{align} f(n) &=\sum_{i=1}^{n}g(n) \\ & =\sum_{i=1}^{n}{\varphi(2n)/2}\\ & =\frac{\sum_{i=1}^{n}{\varphi(2n)}}{2} \end{align} $$$$$$ 所以只需要对欧拉函数进行打表,并求$$$\varphi(2n)$$$的前缀和,就能知道任何的$$$f(n)$$$。

但是做到这还可以继续优化,这道题的n是2e7,但是却需要对前4e7项欧拉函数打表。可以这样优化一下空间:打表发现,欧拉函数满足下面的性质:

$$$$$$\varphi(2n)= \begin{cases} \varphi(n), & \text{n是奇数}\\[2ex] 2\varphi(n), & \text{n是偶数} \end{cases} $$$$$$ 所以可以将$$$f(n)$$$改为:

$$$$$$ \begin{align} f(n) &=\sum_{i=1}^{n}{\frac{(2-i\&1)\varphi(n)}{2}}\\ &=\sum_{i=1}^{n}{\frac{\varphi(n)}{1+i\&1}} \end{align} $$$$$$ 至此,只需要求出$$$\varphi(i)$$$的前2e7项,并求出上面的前缀和,就能在$$$O(nlogn)$$$求出答案。需要注意的是,前缀和需要用long long保存。另外有一点就是,打表4e7项欧拉函数可能会超时,原因在于板子的效率问题,改用效率更高的欧拉函数打表的板子就不存在超时的问题了(不要问我是怎么知道的)。 总结 为什么手速这么慢,一定是有什么地方想复杂了吧。 代码

 

#include<stdio.h>
typedef long long LL;
#define maxn 20000000
int p[maxn+7];
LL arr[maxn+7];

int prepare(){
    int i,j;
    //打表欧拉函数
    for(i=1; i<=maxn; i++)
        p[i]=i;
    for(i=2; i<=maxn; i+=2)
        p[i]/=2;
    for(i=3; i<=maxn; i+=2)
        if(p[i]==i){
            for(j=i; j<=maxn; j+=i)
            p[j]=p[j]/i*(i-1);
        }
       /*把规模从2n缩减到n的原因
    phi(2*n)=   phi(n) n奇数
              2*phi(n) n偶数
    arr[n]  =phi(2)/2+phi(4)/2+...phi(2*n)/?
            =phi(1)/2+phi(2)+...phi(n)/?
    */
    arr[1]=p[1]/2;
    for(int i=2;i<=20000000;++i){
   //求前缀和
        arr[i]=arr[i-1]+p[i]/((i&1)+1);
    }
}

int main(){
    prepare();
    int kase,n;
    for(scanf("%d",&kase);kase;--kase){
        scanf("%d",&n);
        printf("%lld\n",arr[n]);
    }
    
}

 

转载于:https://www.cnblogs.com/tobyw/p/9519801.html

原文链接:https://blog.csdn.net/weixin_30342827/article/details/95840819

本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。

本博客所有文章如无特别注明均为原创。
复制或转载请以超链接形式注明转自起风了,原文地址《hdu 6434 Count (欧拉函数)
   

还没有人抢沙发呢~