hdu 6706

Posted 19992147orz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6706相关的知识,希望对你有一定的参考价值。

杜教筛+欧拉函数

答案等价于

$\sum_i=1^n\sum_j=1^i(i-j)[gcd(i,j)==1]$

欧拉函数$\phi(i)$表示比$i$小且与$i$互质的数的个数

那么进一步化简,答案等于

$\frac\sum_i=1^n\phi(i)*i2-1$

$\phii*i$是一个积性函数,可以杜教筛

设$f(i)=\phi(i)*i$,$g(i)=i$

那么

$f*g=\sum_n|df(d)*\fracnd$

$=\sum_n|d\phi(d)*d*\fracnd$

$=\sum_n|d\phi(d)*n$

$=n\sum_n|d\phi(d)$

因为$\sum_n|d\phi(d)=n$

所以$f*g=n^2$

那么就可以杜教筛了

技术图片
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5, P = 1e9 + 7, inv2 = 500000004, inv6 = 166666668;
int n, a, b;
int phi[maxn], p[maxn], mark[maxn];
map<int, int> mp;
void init() 
    phi[1] = 1;
    for(int i = 2; i < maxn; ++i) 
        if(!mark[i]) 
            p[++p[0]] = i;
            phi[i] = i - 1;
        
        for(int j = 1; j <= p[0] && i * p[j] < maxn; ++j) 
            mark[i * p[j]] = 1;
            if(i % p[j] == 0) 
                phi[i * p[j]] = phi[i] * p[j];
                break;
            
            phi[i * p[j]] = phi[i] * phi[p[j]];
        
    
    for(int i = 1; i < maxn; ++i) 
        phi[i] = (1LL * phi[i] * i % P + phi[i - 1]) % P;
    

int cal(int x) 
    return 1LL * x * (x + 1) % P * inv2 % P;

int dj(int n) 
    if(n < maxn) return phi[n];
    if(mp.find(n) != mp.end()) return mp[n];
    int ret = 1LL * n * (n + 1) % P * (2LL * n + 1) % P * inv6 % P;
    for(int i = 2, j; i <= n; i = j + 1) 
        j = n / (n / i);
        ret = (ret - 1LL * (cal(j) - cal(i - 1) + P) % P * dj(n / i) % P + P) % P;
    
    return mp[n] = ret;

int main() 
    init();
    int T; scanf("%d", &T);
    while(T--) 
        scanf("%d%d%d", &n, &a, &b);
        printf("%d\n", 1LL * (dj(n) - 1) * inv2 % P);
    
    return 0;
 
View Code

 

以上是关于hdu 6706的主要内容,如果未能解决你的问题,请参考以下文章

HDU6706 CCPC 2019网络赛 huntian oy 推式子+杜教筛

CCPC 2019 网络赛 HDU huntian oy (杜教筛)

[CCPC2019 ONLINE]E huntian oy

项目第一天

NGUI -- UILabel

从管道分隔文件中获取值