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)
NQIW4BNX3CA23A$KBBG.png)
所以
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+;
const int MAXN = ; unordered_map<int, long long> Sumiphi;
int prime[MAXN+], cnt;
long long phi[MAXN+];
long long iphi[MAXN+];
bool isprime[MAXN+]; // 线性筛
void getPrime(int n) {
isprime[] = true;
phi[] = ;
for(int i=;i<=n;i++) {
if(!isprime[i])
prime[++cnt] = i, phi[i] = i-; for(int j=;j<=cnt&&prime[j]*i<=n;j++) {
isprime[prime[j]*i] = true;
phi[prime[j]*i] = phi[i]*(prime[j]-);
if(i%prime[j]==) {
phi[prime[j]*i] = phi[i]*(prime[j]);
break;
}
}
}
// 前缀和
for(int i=;i<=n;i++) {
iphi[i] = iphi[i-] + phi[i]*i % mod;
iphi[i] %= mod;
}
} const int _two = (+mod)/;
const int _six = ; // 杜教筛求 ∑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 = ;
for(int i=,j;i<=n;i=j+) {
j = n/(n/i);
sum += iphiSum(n/i)*(j-i+)% mod *(i+j) % mod *_two % mod;
}
Sumiphi[n] = ((1LL*n*(n+)% mod *(*n+)% 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)-+mod)%mod * _two % mod);
}
return ;
}
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 = ;
unordered_map<int, long long> Sumphi;
unordered_map<int, long long> Summu;
int prime[MAXN+], cnt;
long long mu[MAXN+], phi[MAXN+];
bool isprime[MAXN+]; // 线性筛
void getPrime(int n) {
isprime[] = true;
mu[] = ;
phi[] = ;
for(int i=;i<=n;i++) {
if(!isprime[i])
prime[++cnt] = i, phi[i] = i-, mu[i] = -; for(int j=;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]-);
if(i%prime[j]==) {
mu[prime[j]*i] = ;
phi[prime[j]*i] = phi[i]*(prime[j]);
break;
}
}
}
// 前缀和
for(int i=;i<=n;i++) {
mu[i] += mu[i-];
phi[i] += phi[i-];
}
} // 杜教筛求 ∑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 = ;
for(int i=,j;i<=n;i=j+) {
j = n/(n/i);
sum += (j-i+)*muSum(n/i);
}
Summu[n] = - 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 = ;
for(int i=,j;i<=n;i=j+) {
j = n/(n/i);
sum += (j-i+)*phiSum(n/i);
}
Sumphi[n] = 1LL*(n+)*n/ - 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 ;
}
CCPC 2019 网络赛 HDU huntian oy (杜教筛)的更多相关文章
- 2019.02.12 bzoj3944: Sum(杜教筛)
传送门 题意: 思路:直接上杜教筛. 知道怎么推导就很简单了,注意预处理的范围. 然后我因为预处理范围不对被zxyoi教育了(ldx你这个傻×两倍常数活该被卡TLE) 喜闻乐见 代码: #includ ...
- CCPC 2019 网络赛 1006 Shuffle Card
// 签到题,比赛时候写双向链表debug了半天,发现有更好方法,记录一下. Shuffle Card HDU 6707 题意: 有一 \(n\) 张卡片,编号 \(1~n\) ,给定初始编号 ...
- CCPC 2019 网络赛 1002 array (权值线段树)
HDU 6703 array 题意: 给定一个数组 \(a_1,a_2, a_3,...a_n\) ,满足 \(1 \le a[i]\le n\) 且 \(a[i]\) 互不相同. 有两种 ...
- HDU 5608 function [杜教筛]
HDU 5608 function 题意:数论函数满足\(N^2-3N+2=\sum_{d|N} f(d)\),求前缀和 裸题-连卷上\(1\)都告诉你了 预处理\(S(n)\)的话反演一下用枚举倍数 ...
- luoguP4213 【模板】杜教筛(Sum)杜教筛
链接 luogu 思路 为了做hdu来学杜教筛. 杜教筛模板题. 卡常数,我加了register居然跑到不到800ms. 太深了. 代码 // luogu-judger-enable-o2 #incl ...
- HDU6706 huntian oy(2019年CCPC网络赛+杜教筛)
目录 题目链接 思路 代码 题目链接 传送门 思路 看到这题还比较懵逼,然后机房大佬板子里面刚好有这个公式\(gcd(a^n-b^n,a^m-b^m)=a^{gcd(n,m)}-b^{gcd(n,m) ...
- ccpc 网络赛 hdu 6155
# ccpc 网络赛 hdu 6155(矩阵乘法 + 线段树) 题意: 给出 01 串,要么询问某个区间内不同的 01 子序列数量,要么把区间翻转. 叉姐的题解: 先考虑怎么算 \(s_1, s_2, ...
- 2019年南京网络赛E题K Sum(莫比乌斯反演+杜教筛+欧拉降幂)
目录 题目链接 思路 代码 题目链接 传送门 思路 首先我们将原式化简: \[ \begin{aligned} &\sum\limits_{l_1=1}^{n}\sum\limits_{l_2 ...
- HDU 6706 huntian oy(杜教筛 + 一些定理)题解
题意: 已知\(f(n,a,b)=\sum_{i=1}^n\sum_{j=1}^igcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\mod 1e9+7\),\(n\leq1e9\),且 ...
随机推荐
- loj2001[SDOI2017]树点染色
题意:给你一棵树,一开始每个点上的颜色互不相同.三种操作:op1:x到根的路径上的点都染上一种新的颜色.op2:设一条路径的权值为val(x,y),求x到y路径的val.op3:询问x的子树中最大的到 ...
- js 浮点数计算问题
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精确的加法结果. //调用:jsAdd(arg1,arg2) //返回值:arg1加上arg2的精确 ...
- 17. final 关键字
1.flnal修饰成员变量 1)定义: 如果一个变量不想被修改,那么就用final修饰 2)语法 public static final double PI=3.14; 3)注意 1. 被fina ...
- Unity 中调用Android的JAVA代码
首先我们要创建一个android项目 因为项目需要使用Unity提供的接口,所以需要将接口classes.jar引入至当前工程但中.接口包的所在地,打开Finder->应用程序->Unit ...
- MTT学习小记
这是个毒瘤题才有的毒瘤东西--奶一口NOI不考 拆系数FFT: 考虑做NTT时模数不是NTT模数(\(2^a*b+1\))怎么办? 很容易想到拆次数FFT. 比如说现在求\(a*b\),设\(m=\s ...
- Delphi exe实例之间传递cmd参数
{Unit1.pas} 通过这个单元的Button,调用另一个实例: procedure TForm1.Button1Click(Sender: TObject); begin ShellExecut ...
- (转)Java 标注(Annotation)详解
转:http://blog.csdn.net/nbrremix/article/details/7337274 元数据的作用 如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所 ...
- prop不同数据类型设置默认值
vue prop 会接收不同的数据类型,这里列出了 常用的数据类型的设置默认值的写法,其中包含: Number, String, Boolean, Array, Function, Object ...
- 消息中间件kafka学习记录
目录 1. 概述 2. 环境准备 3. 命令行常用命令 4. java api实现 1. 概述 Apache Kafka是一个分布式消息系统,凭借其优异的特性而被广泛使用. 高性能:O(1)复杂度消息 ...
- 如果一个文件块有130M,请问有多少个mapper
如果一个文件块有130M,请问有多少个mapper 130M的文件将被分成2个mapper. 原因:根据FileInputFormat类 有一个成员变量 private static final do ...