科技的力量!!!!!!我德意志科技天下第一!!!

这是一篇需要一点儿科技的题解,但实际上这个科技我认为甚至算不上科技,太 simple 了。

首先是推柿子:

\[\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j)^{i+j}
\]
\[\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=d]d^{i+j}
\]
\[\sum_{d=1}^n\sum_{i=1}^{\lfloor \frac n d \rfloor}\sum_{j=1}^{\lfloor \frac n d \rfloor}[\gcd(i,j)=1](d^d)^{i+j}
\]
\[\sum_{d=1}^n\sum_{i=1}^{\lfloor \frac n d \rfloor}\sum_{j=1}^{\lfloor \frac n d \rfloor}\sum_{k|i,k|j}\mu(k)(d^d)^{i+j}
\]
\[\sum_{d=1}^n\sum_{k=1}^{\lfloor \frac n d \rfloor}\sum_{i=1}^{\lfloor \frac n {dk} \rfloor}\sum_{j=1}^{\lfloor \frac n {dk} \rfloor
}\mu(k)(d^{dk})^{i+j}\]

\[f(d,n)=\sum_{i=1}^n\sum_{j=1}^nd^{i+j}
\]

特别的,当 \(d=1\) 时,\(f(1,n)=n^2\)

否则上面那玩意儿就是:

\[(\sum_{i=1}^nd^i)^2
\]

等比数列求和,在 \(O(\log n)\) 的时间内算出来。

回到原柿:

\[\sum_{d=1}^n\sum_{k=1}^{\lfloor \frac n d \rfloor}\mu(k)f(d^{dk},\lfloor \frac n {dk} \rfloor)
\]

考虑将 \((d^d)^k\) 带入 \(f\)。可以发现 \(f\) 只与 \(d^d\) 的若干次方有关,并且这个幂的上界是 \(O(k \times \lfloor \frac n {dk} \rfloor)=O(n)\)。

考虑对于所有的 \(d^d\) 预处理光速幂数组。可以参考这里,复杂度是 \(O(\sqrt [4] {lim})-O(1)\)。本题的 \(lim\) 为 \(1.5 \times 10^6\),不过实际上当 \(d=1\) 时不需要光速幂数组,所以实际上上界不到 \(10^6\)。别小看这一点,\(2^{20}>10^6\),这导致了空间和时间复杂度得到了改善。

于是我们发现唯一的问题是求 \((d^d)^k-1\) 的逆元。我们使用离线求逆元,这里使用的是封装好的离线求逆元。

以及,这个屑题卡空间,所以我们对 \([1,n]\) 分成若干段,对每一段使用离线求逆元和光速幂。离线求逆元当缓存满了的时候需要清空。

我们发现,每段的长度最好是 \(8\),因为离线求逆元最多只会执行 \(10^5\) 次,且光速幂的预处理不会炸空间。还有一个好处就是,这使得离线求逆元的缓存区很短,能够卡进执行文件的缓存,大大降低了常数。

总复杂度为 \(O(n\sqrt [4] {n}+n\ln n)\)。

优化1:只枚举 \(\mu(k) \neq 0\) 的 \(k\),常数降低。

优化2:当 \(d\) 较大时,能够与其匹配的 \(k\) 过少,此时使用快速幂比光速幂更优。

不过不知道为啥只跑了 1.16s,跑得飞快。。。

code:

#include<cstdio>
#include<vector>
typedef unsigned uint;
typedef __uint128_t L;
typedef unsigned long long ull;
const uint M=1.5e6+5;
uint P,top,pri[M],mu[M];bool zhi[M];
struct FastMod{
ull b,m;
FastMod(ull b):b(b),m(ull((L(1)<<64)/b)){}
friend inline ull operator%(const ull&a,const FastMod&mod){
ull r=a-(L(mod.m)*a>>64)*mod.b;
return r>=mod.b?r-mod.b:r;
}
}mod(2);
struct Pow{
std::vector<uint>p1,p2,p3,p4;
inline void clear(){
std::vector<uint>().swap(p1);std::vector<uint>().swap(p2);
std::vector<uint>().swap(p3);std::vector<uint>().swap(p4);
}
inline void init(register uint x){
register uint i;
p1.reserve(33);p2.reserve(33);p3.reserve(33);p4.reserve(33);
p1[0]=p2[0]=p3[0]=p4[0]=1;
for(p1[1]=x,i=2;i<=32;++i)p1[i]=1ull*p1[i-1]*x%mod;
for(x=p2[1]=p1[32],i=2;i<=32;++i)p2[i]=1ull*p2[i-1]*x%mod;
for(x=p3[1]=p2[32],i=2;i<=32;++i)p3[i]=1ull*p3[i-1]*x%mod;
for(x=p4[1]=p3[32],i=2;i<=32;++i)p4[i]=1ull*p4[i-1]*x%mod;
}
inline uint pow(const uint&x){
return 1ull*p1[x&31]*p2[x>>5&31]%mod*p3[x>>10&31]%mod*p4[x>>15&31]%mod;
}
Pow(){
clear();
}
}p[M>>1];
inline uint pow(uint a,uint b){
uint ans=1;
for(;b;b>>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;
return ans;
}
inline void sieve(const uint&M){
register uint i,j,x;mu[1]=1;
for(i=2;i<=M;++i){
if(!zhi[i])mu[pri[++top]=i]=-1;
for(j=1;j<=top&&(x=i*pri[j])<=M;++j){
zhi[x]=true;if(!(i%pri[j]))break;mu[x]=-mu[i];
}
}
}
inline uint calc(const uint&d,const uint&D,const uint&len,const uint&k,const uint&inv){
uint S=(1ull*D*p[d].pow(len*k)%mod-p[d].pow(k)+P)*inv%mod;
return 1ull*S*S%mod;
}
struct GetAns{
uint ans,len,d[131073],k[131073],l[131073],f[131073],S[131073];bool o[131073];
inline void flush(){
uint i,s;if(!len)return;
for(i=1;i<=len;++i)S[i]=1ull*S[i-1]*f[i]%mod;s=pow(S[len],P-2);
do{
if(o[len])ans=(ans+calc(d[len],f[len]+1,l[len],k[len],1ull*s*S[len-1]%mod))%mod;
else ans=(ans+P-calc(d[len],f[len]+1,l[len],k[len],1ull*s*S[len-1]%mod))%mod;
s=1ull*s*f[len]%mod;
}while(--len);
}
inline void Insert(const uint&cd,const uint&ck,const uint&cl,const uint&cf,const bool&co){
++len;d[len]=cd;k[len]=ck;l[len]=cl;f[len]=cf;o[len]=co;
if(!(len&131071))flush();
}
}q;
inline uint Solve(const uint&n){
const uint&lim4=n/4,&lim3=n/3,lim2=n/2;
register uint i,k,x,ans=0,lst=2;q.ans=q.len=0;
for(i=1;i<=n;++i){
if(mu[i]==1)ans=(ans+1ull*(n/i)*(n/i))%mod;
else if(mu[i])ans=(ans+P-1ull*(n/i)*(n/i)%mod)%mod;
}
for(i=2;(i<<1)<=n;++i){
if(!(i&7)){
q.flush();while(lst^i)p[lst++].clear();
}
p[i].init(pow(i,i));
for(k=1;i*k<=n;++k){
if(mu[k]){
x=p[i].pow(k)-1;
if(!x){
if(mu[k]==1)ans=(ans+1ull*(n/(i*k))*(n/(i*k)))%mod;
else if(mu[k])ans=(ans+P-1ull*(n/(i*k))*(n/(i*k))%mod)%mod;
}
else q.Insert(i,k,n/(i*k),x,mu[k]==1);
}
}
}
q.flush();while(lst^i)p[lst++].clear();
for(ans=(ans+q.ans)%mod;i<=n;++i)k=pow(i,i),ans=(ans+1ull*k*k)%mod;
return ans;
}
signed main(){
uint T,n1,n2,m1,m2;q.S[0]=1;
scanf("%u",&T);
if(T==1)scanf("%u%u",&n1,&m1),sieve(n1),mod=FastMod(P=m1),printf("%u",Solve(n1));
else{
scanf("%u%u%u%u",&n1,&m1,&n2,&m2);
sieve(n1>n2?n1:n2);
mod=FastMod(P=m1);printf("%u\n",Solve(n1));
mod=FastMod(P=m2);printf("%u",Solve(n2));
}
}

闲话:这个 \(O(n\log n)\) 可比官方题解的 \(O(n\log n)\) 靠谱多了。

LGP6825题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. eclipse快捷键 包括查找类、方法、变量

    [Ct rl+T] 搜索当前接口的实现类 1. [ALT +/]    此快捷键为用户编辑的好帮手,能为用户提供内容的辅助,不要为记不全方法和属性名称犯愁,当记不全类.方法和属性的名字时,多体验一下[ ...

  2. 集合、Collection、list、set、HashSet

    一.集合的理解:将多个数据放在一起 简介: 1).可以动态保存任意多个对象,使用比较方便!2).提供了一系列方便的操作对象的方法: add.remove.set. get等 1.集合中的实现和继承图 ...

  3. 流量录制与回放在vivo的落地实践

    一.为什么要使用流量录制与回放? 1.1 vivo业务状况 近几年,vivo互联网领域处于高速发展状态,同时由于vivo手机出货量一直在国内名列前茅,经过多年积累,用户规模非常庞大.因此,vivo手机 ...

  4. 3、架构--cp、scp、rsync、实时监控与同步

    笔记 1.晨考 1.VPN的搭建步骤 2.vpn中的iptables是什么作用? 网络转发 2.昨日问题 1.yum源问题 2.VPN链接正常,但是没办法通过172 3.VPN链接时,出现了DNS错误 ...

  5. opencv笔记--Active contours

    Active Contours 也称作 Snake,通过定义封闭区域曲线的能量函数,并使其最小化得到最终曲线. Active Contours 被用作物体边界精确定位上,opencv 给出了一个实现, ...

  6. opencv笔记---contours

    一 Contour Finding Contours使用 STL-style vector<> 表示,如 vector<cv::Point>, vector<cv::Po ...

  7. Solution -「多校联训」轮回

    \(\mathcal{Description}\)   有 \(n\) 个黑盒,第 \(i\) 个黑盒可以让输入变量以 \(p_i\) 的概率保持不变,以 \(\frac{1-p_i}2\) 的概率加 ...

  8. log4j、logback日志框架与统一接口slf4j说明

    log4j 传入日志框架,老项目中使用较多. 日志级别 根日志级别 log4j.rootLogger=info 默认日志级别,设置后对于没有设置子级别的日志输出都走这个默认值. 子类日志级别 log4 ...

  9. CentOS7更新OpenSSH8

    今天使用漏洞扫描工具扫描了一下系统漏洞,发现有一个openssh版本的漏洞.所以本着安全的原则修复一下. 第一时间打开百度搜索相关内容,大多数是编译安装的.每个人的环境和版本也不一样.有一定连不上去的 ...

  10. MySQL高级优化

    MySQL高级 1.索引是什么? (1)索引是排好序可以快速查找的数据结构 (2)方便快速查找,索引实际上也是一张表所以也是要占内存的 2.索引存在哪里? (1)InnoDB引擎 ①索引是和数据存放在 ...