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+;
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 (杜教筛)的更多相关文章

  1. 2019.02.12 bzoj3944: Sum(杜教筛)

    传送门 题意: 思路:直接上杜教筛. 知道怎么推导就很简单了,注意预处理的范围. 然后我因为预处理范围不对被zxyoi教育了(ldx你这个傻×两倍常数活该被卡TLE) 喜闻乐见 代码: #includ ...

  2. CCPC 2019 网络赛 1006 Shuffle Card

    // 签到题,比赛时候写双向链表debug了半天,发现有更好方法,记录一下.   Shuffle Card HDU 6707 题意:   有一 \(n\) 张卡片,编号 \(1~n\) ,给定初始编号 ...

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

    HDU 6703 array   题意:   给定一个数组 \(a_1,a_2, a_3,...a_n\) ,满足 \(1 \le a[i]\le n\) 且 \(a[i]\) 互不相同.   有两种 ...

  4. HDU 5608 function [杜教筛]

    HDU 5608 function 题意:数论函数满足\(N^2-3N+2=\sum_{d|N} f(d)\),求前缀和 裸题-连卷上\(1\)都告诉你了 预处理\(S(n)\)的话反演一下用枚举倍数 ...

  5. luoguP4213 【模板】杜教筛(Sum)杜教筛

    链接 luogu 思路 为了做hdu来学杜教筛. 杜教筛模板题. 卡常数,我加了register居然跑到不到800ms. 太深了. 代码 // luogu-judger-enable-o2 #incl ...

  6. HDU6706 huntian oy(2019年CCPC网络赛+杜教筛)

    目录 题目链接 思路 代码 题目链接 传送门 思路 看到这题还比较懵逼,然后机房大佬板子里面刚好有这个公式\(gcd(a^n-b^n,a^m-b^m)=a^{gcd(n,m)}-b^{gcd(n,m) ...

  7. ccpc 网络赛 hdu 6155

    # ccpc 网络赛 hdu 6155(矩阵乘法 + 线段树) 题意: 给出 01 串,要么询问某个区间内不同的 01 子序列数量,要么把区间翻转. 叉姐的题解: 先考虑怎么算 \(s_1, s_2, ...

  8. 2019年南京网络赛E题K Sum(莫比乌斯反演+杜教筛+欧拉降幂)

    目录 题目链接 思路 代码 题目链接 传送门 思路 首先我们将原式化简: \[ \begin{aligned} &\sum\limits_{l_1=1}^{n}\sum\limits_{l_2 ...

  9. 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\),且 ...

随机推荐

  1. vue v-for 组件传值 enter传值

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. jq-demo-购物车

    首页 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title& ...

  3. phpstrom 注释效果

    /** * .,:,,, .::,,,::. * .::::,,;;, .,;;:,,....:i: * :i,.::::,;i:. ....,,:::::::::,.... .;i:,. ..... ...

  4. js设置当前窗口为最上层窗口

    实际使用iframe框架时会遇到当前窗口页面不能位于最上层窗口的情况,或者是防止自己的网站被别人放在他们的iframe中,这时就需要设置: <script language="java ...

  5. 堡垒机介绍及实现 (使用python django实现)(一)

    堡垒机介绍及实现 (使用python django实现)(一) 堡垒机的功能 我们在使用服务器的时候,通常的方式是 ssh user@ip 然后输入password 多人同时使用,就需要多个账号.这时 ...

  6. Centos6.5安装ruby2.2.3

    一.安装库 Yum install –y gcc* openssl* wget 二.安装ruby wget https://cache.ruby-lang.org/pub/ruby/2.2/ruby- ...

  7. jQuery 表单域选中选择器

    复选框.单选按钮.下拉列表 /***********************************************/ <script type="text/javascrip ...

  8. 3.3_springBoot2.1.x检索之RestHighLevelClient方式

    1.版本依赖 注意对 transport client不了解先阅读官方文档: transport client(传送门) 这里需要版本匹配,如失败查看官网或百度. pom.xml <?xml v ...

  9. linux安装openoffice,并解决中文乱码

    1.安装openoffice 官网http://www.openoffice.org/zh-cn/download/下载 2.解压并进入文件夹: cd /zh-cn/RPMS yum localins ...

  10. 科普帖:深度学习中GPU和显存分析

    知乎的一篇文章: https://zhuanlan.zhihu.com/p/31558973 关于如何使用nvidia-smi查看显存与GPU使用情况,参考如下链接: https://blog.csd ...