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

1005 huntian oy (HDU 6706

题意:

,有T次询问,求 f(n, a, b)。

其中 T = 10^4,1 <= n,a,b <= 1e9,保证每次 a,b互质。

思路:

首先我们需要知道

公式:  gcd(a^n - b^n, a^m - b^m) = a^(gcd(m,n)) - b^(gcd(m,n))

由a,b互质,原式即为

      f(n, a, b) = ∑∑ (i-j)*[(i,j)=1] = ∑ (i*∑ [(i, j)=1] ) - ∑∑ j*[(i, j)=1]

然后我们还要知道

欧拉函数定义式:    phi(n) =  ∑ [(i, n)=1]

1…n中与n互质的数的和: ∑ i*[(i, n)=1] = phi(n)*n / 2,n>1,(n==1时 和为1)

所以

      f(n, a, b) = ∑ i*phi(i) - (∑ phi(i)*i/2 + 1/2) = (∑ i*phi(i)  - 1) / 2

现在问题变成 求 i*phi(i) 的前缀和。由于 n 很大,达到 10^9,线性时间是不够的,要用到杜教筛

不懂杜教筛?出门右拐先去这篇博客研究研究。学会了可以先尝试本篇博客后面的模板题:洛谷P4213

预处理 √n 以内的前缀和后,剩下部分利用整除分块求解的时间复杂度为 O(n^(3/4)),预处理前 k = n^(2/3) 时 时间复杂度可以优化到 O(n^(2/3))。详见大佬的博客分析

AC代码:

#include <cstdio>
#include <unordered_map>
using namespace std;
const int mod = 1e9+7;
const int MAXN = 1000000;

unordered_map<int, long long> Sumiphi;
int prime[MAXN+5], cnt;
long long phi[MAXN+5];
long long iphi[MAXN+5];
bool isprime[MAXN+5];

// 线性筛
void getPrime(int n) {
    isprime[1] = true;
    phi[1] = 1;
    for(int i=2;i<=n;i++) {
        if(!isprime[i])
            prime[++cnt] = i, phi[i] = i-1;

        for(int j=1;j<=cnt&&prime[j]*i<=n;j++) {
            isprime[prime[j]*i] = true;
            phi[prime[j]*i] = phi[i]*(prime[j]-1);
            if(i%prime[j]==0) {
                phi[prime[j]*i] = phi[i]*(prime[j]);
                break;
            }
        }
    }
    // 前缀和
    for(int i=1;i<=n;i++) {
        iphi[i] = iphi[i-1] + phi[i]*i % mod;
        iphi[i] %= mod;
    }
}

const int _two = (1+mod)/2;
const int _six = 166666668;

// 杜教筛求 ∑i*phi(i)
// S(n) = ∑i^2 - ∑d*S(n/d) = n*(n+1)*(2n+1)/6 - ∑d×S(n/d)
long long iphiSum(int n) {
    if(n<=MAXN)
        return iphi[n];
    if(Sumiphi.count(n))
        return Sumiphi[n];

    long long sum = 0;
    for(int i=2,j;i<=n;i=j+1) {
        j = n/(n/i);
        sum += iphiSum(n/i)*(j-i+1)% mod *(i+j) % mod *_two % mod;
    }
    Sumiphi[n] = ((1LL*n*(n+1)% mod *(2*n+1)% mod *_six % mod - sum)%mod + mod) % mod;
    return Sumiphi[n];
}

// 答案:
// ( Sum(i*phi(i)) - 1 ) /2
int main() {
    getPrime(MAXN);
    int T, n, a, b;
    scanf("%d", &T);
    while(T--) {
        scanf("%d %d %d", &n, &a, &b);
        printf("%lld\n", (iphiSum(n)-1+mod)%mod * _two % mod);
    }
    return 0;
}

P4213 【模板】杜教筛(Sum)

题意:

给定一个正整数 N (N<=2^31-1),求

AC模板:

#include <cstdio>
#include <unordered_map>
using namespace std;
// 参考自:https://www.cnblogs.com/dreagonm/p/10077979.html

const int MAXN = 5000000;
unordered_map<int, long long> Sumphi;
unordered_map<int, long long> Summu;
int prime[MAXN+5], cnt;
long long mu[MAXN+5], phi[MAXN+5];
bool isprime[MAXN+5];

// 线性筛
void getPrime(int n) {
    isprime[1] = true;
    mu[1] = 1;
    phi[1] = 1;
    for(int i=2;i<=n;i++) {
        if(!isprime[i])
            prime[++cnt] = i, phi[i] = i-1, mu[i] = -1;

        for(int j=1;j<=cnt&&prime[j]*i<=n;j++) {
            isprime[prime[j]*i] = true;
            mu[prime[j]*i] = -mu[i];
            phi[prime[j]*i] = phi[i]*(prime[j]-1);
            if(i%prime[j]==0) {
                mu[prime[j]*i] = 0;
                phi[prime[j]*i] = phi[i]*(prime[j]);
                break;
            }
        }
    }
    // 前缀和
    for(int i=1;i<=n;i++) {
        mu[i] += mu[i-1];
        phi[i] += phi[i-1];
    }
}

// 杜教筛求 ∑u(i)
// S(n) = 1 - ∑S(n/d)
long long muSum(int n) {
    if(n<=MAXN)
        return mu[n];
    if(Summu.count(n))
        return Summu[n];

    int sum = 0;
    for(int i=2,j;i<=n;i=j+1) {
        j = n/(n/i);
        sum += (j-i+1)*muSum(n/i);
    }
    Summu[n] = 1 - sum;
    return Summu[n];
}

// 杜教筛求 ∑phi(i)
// S(n) = ∑ i - ∑S(n/d)
long long phiSum(int n) {
    if(n<=MAXN)
        return phi[n];
    if(Sumphi.count(n))
        return Sumphi[n];

    long long sum = 0;
    for(int i=2,j;i<=n;i=j+1) {
        j = n/(n/i);
        sum += (j-i+1)*phiSum(n/i);
    }
    Sumphi[n] = 1LL*(n+1)*n/2 - sum;
    return Sumphi[n];
}

int main() {
    getPrime(MAXN);
    int T, n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        printf("%lld %d\n", phiSum(n), muSum(n));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/izcat/p/11406534.html

时间: 2024-10-08 00:22:43

CCPC 2019 网络赛 HDU huntian oy (杜教筛)的相关文章

hdu 6076 huntian oy 杜教筛

打表观察得到,gcd(i,j)==1时,gcd(i^a−j^a,i^b−j^b)的值为i - j.所以,你发现这个题跟ab就没关系了... 变成去求∑∑(i-j)[gcd(i,j) == 1]了.有一个显然的结论,gcd(i,j) == gcd(i-j,i). 设k为i-j,则变成 ∑(i 1->n)∑k(1->i-1)[gcd(i,k) == 1]. 又因为i和i本身,一定不互质,所以变成 ∑(i 1->n)∑k(1->i)[gcd(i,k) == 1].然后有个结论,1…N中与

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

CCPC 2019 网络赛 HDU 6706 huntian oy 标签 奇奇怪怪的数论结论 杜教筛 前言 我的csdn和博客园是同步的,欢迎来访danzh-博客园~ 简明题意 给定n,a,b,求: \[\sum_{i=1}^n\sum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\%(10^9+7)\] 思路 首先有一个结论: \[gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)}-j^{gcd(a,b)}\] 上面的结论对于i,j互质是成立的

CCPC 2019 网络赛 1002 array (权值线段树)

HDU 6703 ? 题意: ? 给定一个数组 \(a_1,a_2, a_3,...a_n\) ,满足 \(1 \le a[i]\le n\) 且 \(a[i]\) 互不相同. ? 有两种操作:1. 将 \(a[pos]\) 的值加上 100000000:2. 询问不等于任何 \(a[i], (1 \le i \le r)\) 且不小于 \(k\) 的最小值. ? 思路: ? 注意 \(n,k\) 的范围都不超过 100000,对于操作一,相当于删除了这个数(询问的答案一定在区间 \([1, n

CCPC 2017 网络赛

1001.我们的想法是,先构造n个要删掉的点,然后不断给图加边,使得每条边的其中一个点在n个点之中. 我们要使n个点之外的点尽量多,并且每次删掉的点在n个点之外. 贪心的决策是,每次操作,前n个点的度和令外的最大度的点度数相同. 然后删掉这个点之后,之后的操作,剩余的点也满足这个要求.所以度数最大的点必定与n个点有边. 于是可以这样构造,增加n批点(i = 1~n),每次增加n/i个点的,每个增加的点连出i条边到n个点. 这样,n个点每次增加的最大度数不超过1.但每次删点的时候(按n~1批的顺序

2019CCPC网络赛 HD6707——杜教筛

题意 求 $f(n,a,b)=\sum_{i=1}^n \sum_{j=1}^i gcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\%(10^9+7)$,$1 \le n,a,b \le 10^9$,共有 $T$ 组测试,其中只有10组的 $n$ 大于 $10^6$. 分析 首先,当 $i, j$互质,$a, b$互质时,有 $gcd(i^a-j^a,i^b-j^b)=i-j$(证明见 链接),也可以打表猜一猜嘛. 可以推出:$$\sum_{d=1}^{N}\mu(d)\cdot

EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)

传送门 题意: 统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\). 定义\(f(n,k)\)为满足要求的\(k\)元组个数,现在要求出\(\sum_{i=1}^n f(i,k),1\leq n\leq 10^9,1\leq k\leq 1000\). 思路: 首先来化简一下式子,题目要求的就是: \[ \begin{aligned} &\sum_{i=1}^n\sum_{j=1

杜教筛 学习总结

看了看唐老师的blog,照猫画虎的做了几道题目,感觉对杜教筛有些感觉了 但是稍微有一点难度的题目还是做不出来,放假的时候争取都A掉(挖坑ing) 这篇文章以后等我A掉那些题目之后再UPD上去就好啦 由于懒得去写怎么用编辑器写公式,所以公式就准备直接copy唐老师的啦 首先积性函数和完全积性函数什么的就不再多说了 列举常见的积性函数: 1.约数个数函数和约数个数和函数 2.欧拉函数phi 3.莫比乌斯函数mu 4.元函数e 其中e(n)=[n==1] 5.恒等函数I 其中I(n)=1 6.单位函数

【学术篇】分析矿洞 杜教筛

数论什么的都去死吧! 看着题解我都能化式子用完4页草纸... 另外吐槽一句出题人的拼音学的是真好, 不知道是不是故意的. 其实题解已经写得挺详细的了. 我就是提一些出题人觉得太easy没必要提但是做题还是需要的一些东西....(因为这些东西我基本都是现学的) 然而之前刚刚学完mobius反演就暂时性脱坑的我啥也不会啊.. 看到前排dp和曲神在水luogu的欢(bao/du)乐(ling/liu)赛, 就想去看看. 然后就点了报名但是发现自己什么都不会. 去看了看T1. 就是这道题. 然后成功的化

P4213【模板】杜教筛(Sum)

思路:杜教筛 提交:\(2\)次 错因:\(\varphi(i)\)的前缀和用\(int\)存的 题解: 对于一类筛积性函数前缀和的问题,杜教筛可以以低于线性的时间复杂度来解决问题. 先要构造\(h=f*g\),并且\(h\)的前缀和易求,\(g\)的区间和易求. 具体地: \[\sum_{i=1}^{n}h(i)=\sum_{i=1}^{n}\sum_{d|i}g(d)\cdot f(\frac{i}{d})\] \[\sum_{i=1}^{n}h(i)=\sum_{d=1}^{n}g(d)\