【SPOJ-GCDEX】GCD Extreme(欧拉函数)
题目:
分析:
求:
\]
这道题给同届新生讲过,由于种种原因只讲了 \(O(n)\) 预处理欧拉函数 \(O(n)\) 查询的暴力做法,顺带提了一句 “这题能根号查询” 被教练嘴了 QAQ 。以及小恐龙给我说有 \(O(n\log n)\) 预处理 \(O(1)\) 查询的另一种写法。
重点是前几天某学长讲课讲这道题,才知道有 \(O(n)\) 预处理 \(O(1)\) 查询的神仙做法,并且据说因为 SPOJ 上时限 0.237s ,复杂度比这个高的都过不去(只交了最后一种,所以我也不知道是真的假的……)。下面分别介绍这三种做法(在无特殊说明的情况下,本文中所有除法均为向下取整):
方法一
为了方便计算,先给和式中添上 \(\sum_{i=1}^{n}gcd(i,i)=\frac{n(n+1)}{2}\),再换一下枚举顺序,得到:
\]
然后先枚举 \(gcd(i,j)\) 的值,并把 \(i\) 变成 \(i\cdot d\),\(j\) 变成 \(j\cdot d\) :
\]
(方括号表示其中式子成立时值为 \(1\) ,否则为 \(0\) )
根据欧拉函数的定义( \(\varphi(x)\) 表示不超过 \(x\) 的与 \(x\) 互质的正整数的个数),得到:
\]
(其中 \(S_\varphi\) 表示 \(\varphi\) 的前缀和,即 \(S_\varphi(x)=\sum_{i=1}^{x}\varphi(x)\) )
用线性筛处理出欧拉函数前缀和后数论分块即可。预处理 \(O(n)\) ,查询 \(O(\sqrt{n})\) 。
方法二
设:
\]
则答案为:
\]
考虑如何计算 \(F(i)\) 。同样先枚举 \(gcd(i,j)\) 的值:
\]
于是先线性筛 \(\varphi\) ,然后枚举 \(d\) ,每个 \(d\) 向所有 \(F(i\cdot d) (0<i\leq \frac{n}{d})\) 贡献 \(d\cdot \varphi(i)\) 。最后处理 \(F\) 函数的前缀和。预处理时间复杂度为 \(n\) 乘上 \(\sum_{i=1}^{n}\frac{1}{i}\),约为 \(O(n\log n)\) 。可以 \(O(1)\) 查询。
方法三:
接着方法二:
\]
则答案为:
\]
考虑如果已经求出了 \(F(n)\) ,则有(其中 \(p\) 是质数且与 \(n\) 互质):
\]
对于和式的每一项,这个 \(p\) 要么乘到 \(d\) 上,要么乘到 \(\varphi(i)\) 上,而欧拉函数是积性函数所以 \(\varphi(ip)=p\cdot \varphi(i)\) 。
这个性质很好,如果能快速计算 \(n=p^k\) (\(p\) 是质数)的情况就能愉快地线性筛了。(为什么?请看 【知识总结】线性筛_杜教筛_Min25筛 的线性筛部分)
考虑当 \(n=p^k\) ,\(F(n)=\sum_{i=0}^{k}p^{k-i}\varphi(p^i)\) 。根据欧拉函数的公式:
\]
(注意当 \(i=0\) 时 \(p^0=1\) 中没有因子 \(p\) ,要特殊处理)
所以当 \(k>1\) , \(F(p^{k-1})=(k-1)p^{k-2}(p-1)+p^{k-1}\) ,给它乘上 \(p\) 再加上 \(p^{k-1}(p-1)\) 就是 \(F(p^k)\) 。 \(k=1\) (即 \(n\) 是质数)的情况直接手算一下,等于 \(2n-1\) 。
于是可以线性筛出 \(F\) 函数然后处理前缀和, \(O(n)\) 预处理 \(O(1)\) 查询。
代码:
(方法三)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
namespace zyt
{
template<typename T>
inline bool read(T &x)
{
char c;
bool f = false;
x = 0;
do
c = getchar();
while (c != EOF && c != '-' && !isdigit(c));
if (c == EOF)
return false;
if (c == '-')
f = true, c = getchar();
do
x = x * 10 + c - '0', c = getchar();
while (isdigit(c));
if (f)
x = -x;
return true;
}
template<typename T>
inline void write(T x)
{
static char buf[20];
char *pos = buf;
if (x < 0)
putchar('-'), x = -x;
do
*pos++ = x % 10 + '0';
while (x /= 10);
while (pos > buf)
putchar(*--pos);
}
typedef long long ll;
const int N = 1e6 + 10;
ll f[N];
int prime[N], last[N], cnt;
bool mark[N];
void init()
{
f[1] = 1;
for (int i = 2; i < N; i++)
{
if (!mark[i])
prime[cnt++] = last[i] = i, f[i] = i * 2 - 1;
for (int j = 0; j < cnt && (ll)i * prime[j] < N; j++)
{
int k = i * prime[j];
mark[k] = true;
if (i % prime[j] == 0)
{
last[k] = last[i] * prime[j];
if (last[k] == k)
f[k] = f[i] * prime[j] + (ll)i * (prime[j] - 1);
else
f[k] = f[i / last[i]] * f[last[k]];
}
else
{
last[k] = prime[j];
f[k] = f[i] * f[prime[j]];
}
}
}
for (int i = 1; i < N; i++)
f[i] += f[i - 1];
}
int work()
{
int n;
init();
while (read(n) && n)
write(f[n] - (ll)(n + 1) * n / 2), putchar('\n');
return 0;
}
}
int main()
{
return zyt::work();
}
【SPOJ-GCDEX】GCD Extreme(欧拉函数)的更多相关文章
- spoj 3871. GCD Extreme 欧拉+积性函数
3871. GCD Extreme Problem code: GCDEX Given the value of N, you will have to find the value of G. Th ...
- hdu2588 GCD (欧拉函数)
GCD 题意:输入N,M(2<=N<=1000000000, 1<=M<=N), 设1<=X<=N,求使gcd(X,N)>=M的X的个数. (文末有题) 知 ...
- uva11426 gcd、欧拉函数
题意:给出N,求所有满足i<j<=N的gcd(i,j)之和 这题去年做过一次... 设f(n)=gcd(1,n)+gcd(2,n)+......+gcd(n-1,n),那么answer=S ...
- HDU 1695 GCD (欧拉函数+容斥原理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- HDU 1787 GCD Again(欧拉函数,水题)
GCD Again Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- hdu 4983 Goffi and GCD(欧拉函数)
Problem Description Goffi is doing his math homework and he finds an equality on his text book: gcd( ...
- hdu 1695 GCD(欧拉函数+容斥)
Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD( ...
- HDU 1695 GCD(欧拉函数+容斥原理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:x位于区间[a, b],y位于区间[c, d],求满足GCD(x, y) = k的(x, ...
- GCD(欧拉函数)
GCD Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...
- HDU 2588 GCD(欧拉函数)
GCD Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
随机推荐
- 【NOIP2017练习】怎样学习哲学(计数,DP)
题意:OI大师抖儿在夺得银牌之后,顺利保送pku.这一天,抖儿问长者:“虽然我已经保送了,但是我还要参加学考.马上就要考政治了,请问应该怎样学习哲学,通过政治考试?” 长者回答:“你啊,Too Yo ...
- 2015山东信息学夏令营 Day4T3 生产
2015山东信息学夏令营 Day4T3 生产 [题目描述] 工厂为了生产一种复杂的产品,给各个生产部门制定了详细的生产计划.那么,就经常会有生产部门要把产品送到另一个生产部门作为原料.这是一个注重产品 ...
- AOJ731(不等式)
题意:有n(n<=100)个石头,每个石头的价值在Ai~Bi(1<=Ai<=Bi<=10000)之间,将这些石头分给两个人,求两个人的最大总价值差的最小值 分析: 与一般的求最 ...
- mysql实现oracle序列
mysql实现oracle序列的方案1.建表,表结构为:drop table if exists sequence; create table sequence ( seq_name VARCHAR( ...
- operamasks—omGrid/omBorderLayout的混合使用
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="test.aspx.cs&q ...
- "Simple Factory" vs "Factory Method" vs "Abstract Factory" vs "Reflect"
ref: http://www.cnblogs.com/zhangchenliang/p/3700820.html 1. "Simple Factory" package torv ...
- go语言中的timer 和ticker定时任务
https://mmcgrana.github.io/2012/09/go-by-example-timers-and-tickers.html --------------------------- ...
- 华为OJ2051-最小的K个数(Top K问题)
一.题目描述 描述: 输入n个整数,输出其中最小的k个. 输入: 输入 n 和 k 输入一个整数数组 输出: 输出一个整数数组 样例输入: 5 2 1 3 5 7 2 样例输出: 1 2 二.Top ...
- Photoshop制作的ico图标方法
photoshop是打不开ico的.只是能够通过安装插件实现. 插件点击这里能够下载. 用法,解压后的插件文件 粘贴到: (英文版路径) /program files/adobe/photoshop ...
- [DLX反复覆盖] poj 1084 Square Destroyer
题意: n*n的矩形阵(n<=5),由2*n*(n+1)根火柴构成,那么当中会有非常多诸如边长为1,为2...为n的正方形,如今能够拿走一些火柴,那么就会有一些正方形被破坏掉. 求在已经拿走一些 ...