2019ICPC西安邀请赛 - B. Product - 数论
打印的时候麻烦把:https://blog.csdn.net/skywalkert/article/details/50500009这个打印下来。
求\(\prod\limits_{i=1}^{n} \prod\limits_{j=1}^{n} \prod\limits_{k=1}^{n} m^{gcd(i,j)[k|gcd(i,j)]} mod p\)
欧拉定理:
\(m^{ \sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} \sum\limits_{k=1}^{n} {gcd(i,j)[k|gcd(i,j)]} mod (p-1) }mod p\)
算出指数直接套快速幂就可以了。考虑指数怎么算。为了方便把取模省略。
$\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} \sum\limits_{k=1}^{n} {gcd(i,j)[k|gcd(i,j)]} $
这种带个整除的,一般都是交换求和到前面,然后后面算他的倍数。
$=\sum\limits_{k=1}^{n} \sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} {gcd(i,j)[k|gcd(i,j)]} $
带方括号的,枚举g,去括号。把g放在前面。
$=\sum\limits_{g=1}{n}g\sum\limits_{k=1}{n} \sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} {[gcd(i,j)==g][k|g]} $
k与i,j无关了,提到前面。
$=\sum\limits_{g=1}{n}g\sum\limits_{k=1}{n} [k|g] \sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} {[gcd(i,j)==g]} $
那么这个k就是d(g)了。
$=\sum\limits_{g=1}^{n}g*d(g) \sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} {[gcd(i,j)==g]} $
后面那个就把g提出来,好像还是很套路的。在什么鬼GCD统计里见过下式:
$\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{n} {[gcd(i,j)g]} \(
\) = \sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor} \sum\limits_{j=1}^{\lfloor\frac{n}{g}\rfloor} {[gcd(i,j)1]} $
那么这个两个数的互质对,规定i比j大于等于,那么就是欧拉函数,特别的,\(\varphi(1)=1\)。(i,j)和(j,i)互换重复计算(1,1)。
$ = \sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor} \sum\limits_{j=1}^{\lfloor\frac{n}{g}\rfloor} {[gcd(i,j)==1]} \(
\) = 2 ( \sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor} \varphi(i) ) - 1 $
这个东西用杜教筛板子都不用思考任何东西,直接弄出来(说起来我的杜教筛好像多个log)。
记上面的算式为 \(S(\lfloor\frac{n}{g}\rfloor)\) ,那么原来的简化为:
$=\sum\limits_{g=1}^{n}g*d(g) S(\lfloor\frac{n}{g}\rfloor) $
换个喜欢的字母!!!
$=\sum\limits_{i=1}^{n}i*d(i) S(\lfloor\frac{n}{i}\rfloor) $
这些都跟g有关,太自闭了,大半时间卡在这里。后面的函数明显可以分块到 \(O(\sqrt{n})\),对于一段连续的i求出结果。
要是可以计算前面的 \(\sum\limits_{i=1}^{n}i*d(i)\) 的前缀和,那么可以再花\(O(1)\)求出一段连续的i的求和结果和后面相乘。
最后的问题就是怎么快速计算 \(\sum\limits_{i=1}^{n}i*d(i)\) 这个狗东西。
首先可以线性预处理到5e6左右,花费一大堆内存,因为d(i)我是有线性筛的(虽然不会他的杜教筛)。
(菜鸡的)第一次重要的突破!
每个数的贡献和他的因子个数成线性。
然后我突发奇想,枚举每个因子d,枚举到 \(\sqrt{n}\) ,每个因子会使得他的每个倍数都恰好多贡献1倍,那么就是 \(d+2d+3d+...+\lfloor\frac{n}{d}\rfloor * d\)。
等差数列求和嘛!
那么就变成:
\(\sum\limits_{i=1}^{n}i*d(i)\)
\(=\sum\limits_{d=1}^{\lfloor\sqrt{n}\rfloor} \frac{d*(1+\lfloor\frac{n}{d}\rfloor)*(\lfloor\frac{n}{d}\rfloor)}{2}\)
已经变成 \(O(\sqrt{n})\)求的了,当时出不了第三个样例,怎么想也是哦,能出就奇怪了。
(菜鸡的)第二次重要的突破!
233,看了半天才发现,上面不是也可以分块求的吗?对\(\lfloor\frac{n}{d}\rfloor\)分块啊。对一段连续的d,\(\lfloor\frac{n}{d}\rfloor\)都是同一个值,想了半天才领会!
那么就可以 \(O(n^{\frac{1}{4}})\) 求出\(\sum\limits_{i=1}^{n}i*d(i)\) 了,把这个狗东西记为 \(T(i)\)
$=\sum\limits_{i=1}^{n}T(i) S(\lfloor\frac{n}{i}\rfloor) $
杜教筛预处理 \(O(n^{\frac{2}{3}})\) ,单次询问S(x)差不多 \(O(1)\) ,虽然我的杜教筛比dq的多了一点东西。
单次询问T(i)差不多 \(O(n^{\frac{1}{4}})\) 。意思是对单个i,处理出答案需要 \(O(n^{\frac{1}{4}})\) 。
求和时,第一次分块对i分块用了 \(O(\sqrt{n})\),每段连续的i共用一个T(i) S(\lfloor\frac{n}{i}\rfloor) ,所以就是 \(O(n^{\frac{3}{4}})\) 。n是1e9,刚刚好够。
其他注意点:
1.应该用欧拉定理,这里卡了很久!幂取模不是直接取的,不要搞假算法!
2.涉及除法的运算,恰好求和公式可以约掉那个2,不要对那个数字取模!
总结:
\(\sum\limits_{i=1}^{n}i*d(i)=\sum\limits_{d=1}^{\lfloor\sqrt{n}\rfloor} \frac{d*(1+\lfloor\frac{n}{d}\rfloor)*(\lfloor\frac{n}{d}\rfloor)}{2}\) 可以 \(O(n^{\frac{1}{4}})\) 计算。
同理可得 \(\sum\limits_{i=1}^{n}d(i)=\sum\limits_{d=1}^{\lfloor\sqrt{n}\rfloor} \frac{(1+\lfloor\frac{n}{d}\rfloor)*(\lfloor\frac{n}{d}\rfloor)}{2}\) 也是一样的。
说白了是我不会计算\(d(i)\)前缀和的方法,过于依赖线性筛了,去关注一下单个xx函数的求法吧。
当时写的代码,270分钟1A,好像挤到金银分隔线。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=5e6;
ll n,m,p,mod;
ll inv2;
ll qpow(ll x,ll n)
{
ll res=1%p;
while(n)
{
if(n&1)
res=(res*x)%p;
x=(x*x)%p;
n>>=1;
}
return res%p;
}
ll Qarray[MAXN+5];
//Q(n)=\sum_i=1^n i*d(i)
inline ll Q(ll n)
{
if(n<=MAXN)
return Qarray[n];
ll res=0;
for(ll l=1,r;l<=n; l=r+1){
r=n/(n/l);
ll t=n/l;
ll tmp1=((t+1)*t/2)%mod;
ll tmp2=((l+r)*(r-l+1)/2)%mod;
res=(res+(tmp1*tmp2%mod))%mod;
}
return res%mod;
}
unordered_map<int,ll> Sphi;
ll sump[MAXN+5];
int pri[MAXN+5],pritop;
bool notpri[MAXN+5];
ll d[MAXN+5],a[MAXN+5];
void sieve(int n=MAXN)
{
pritop=0;
notpri[1]=1;
sump[1]=1;
d[1]=1;
for(int i=2; i<=n; i++)
{
if(!notpri[i])
{
pri[++pritop]=i;
d[i]=2;
a[i]=1;
sump[i]=(i-1)%mod;
}
for(int j=1; j<=pritop&&i*pri[j]<=n; j++)
{
notpri[i*pri[j]]=1;
if(i%pri[j])
{
d[i*pri[j]]=d[i]*d[pri[j]];
a[i*pri[j]]=1;
sump[i*pri[j]]=sump[i]*sump[pri[j]]%mod;
}
else
{
d[i*pri[j]]=d[i]/(a[i]+1)*(a[i]+2);
a[i*pri[j]]=a[i]+1;
sump[i*pri[j]]=sump[i]*pri[j]%mod;
break;
}
}
}
Qarray[0]=0;
Qarray[1]=1;
for(int i=2; i<=n; i++)
{
sump[i]=(sump[i-1]+sump[i])%mod;
Qarray[i]=(Qarray[i-1]+1ll*i*d[i])%mod;
}
return;
}
inline ll GetSphi(int n)
{
if(n<=MAXN)
return sump[n];
if(Sphi.count(n))
return Sphi[n];
ll ret=n;
if(ret%2==0)
ret=(ret/2)*(1ll+n);
else
ret*=(1ll+n)/2;
for(ll l=2,r;l<=n; l=r+1)
{
ll t=n/l;
r=n/(t);
ret-=(r-l+1)*GetSphi(t);
}
ret%=mod;
return Sphi[n]=ret;
}
int main()
{
#ifdef local
freopen("Yinku.in","r",stdin);
#endif // local
scanf("%lld%lld%lld",&n,&m,&p);
mod=p-1;
sieve();
ll ans=0;
for(ll l=1,r; l<=n; l=r+1)
{
ll t=n/l;
r=n/t;
ll tmp=(Q(r)-Q(l-1)+mod)%mod;
ll tmp2=GetSphi(t)%mod;
ans=(ans+tmp*tmp2%mod)%mod;
}
//printf("ans=%lld\n",ans);
ans=(ans*2ll)%mod;
ans=(ans-Q(n)+mod)%mod;
//printf("ans=%lld\n",ans);
ll Ans=qpow(m,ans%mod);
printf("%lld\n",Ans);
return 0;
}
2019ICPC西安邀请赛 - B. Product - 数论的更多相关文章
- 计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛
Tree Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered ...
- 2019ICPC西安邀请赛(计蒜客复现赛)总结
开始时因为吃饭晚了一刻钟,然后打开比赛.看了眼榜单A题已经过了二十来个队伍了,宝儿就去做A. 传师说最后一题看题目像最短路,于是我就去看M了,宝儿做完之后也来陪我看.M一开始看到时以为是像 POJ ...
- 计蒜客 39280.Travel-二分+最短路dijkstra-二分过程中保存结果,因为二分完最后的不一定是结果 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M.) 2019ICPC西安邀请赛现场赛重现赛
Travel There are nn planets in the MOT galaxy, and each planet has a unique number from 1 \sim n1∼n. ...
- 计蒜客 39279.Swap-打表找规律 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest L.) 2019ICPC西安邀请赛现场赛重现赛
Swap There is a sequence of numbers of length nn, and each number in the sequence is different. Ther ...
- 计蒜客 39270.Angel's Journey-简单的计算几何 ((The 2019 ACM-ICPC China Shannxi Provincial Programming Contest C.) 2019ICPC西安邀请赛现场赛重现赛
Angel's Journey “Miyane!” This day Hana asks Miyako for help again. Hana plays the part of angel on ...
- 计蒜客 39268.Tasks-签到 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest A.) 2019ICPC西安邀请赛现场赛重现赛
Tasks It's too late now, but you still have too much work to do. There are nn tasks on your list. Th ...
- 2019icpc西安邀请赛 J And And And (树形dp)
题目链接:https://nanti.jisuanke.com/t/39277 题意:给出一棵有边权的树,求所有简单路径包含异或和为0的简单路径的总数和. 思路: 首先,对于异或为0这一限制,我们通过 ...
- 【2019ICPC西安邀请赛】J.And And And(点分治,贡献)
题意:给定一棵n个点带边权的树,定义每条路径的值为路径上边权的异或和 如果一条路径的值为0,其对答案的贡献为所有包含这条路径的路径条数 求答案膜1e9+7 n<=1e5,0<=边权< ...
- 2019icpc西安邀请赛
来源:https://www.jisuanke.com/contest/2625?view=challenges 更新中 A.Tasks 直接贪心 代码:听说当时很多队伍提前拆题甚至上机了,所以很多0 ...
随机推荐
- Nginx详细的安装教程(linux)
转:https://blog.csdn.net/u013641234/article/details/73838472 Nginx作为一个web服务器,目前使用最多的就利用其负载均衡,本篇着重讲解的是 ...
- 自动提交form表单
<form class="form-inline" name='MD5form' method="post" action="<?php ...
- Bullet Physics OpenGL 刚体应用程序模板 Rigid Simulation in Bullet
利用Bullet物理引擎实现刚体的自由落体模拟的模板 Bullet下载地址 Main.cpp #include <GLUT/glut.h> #include <cstdlib> ...
- 【BZOJ2338】[HNOI2011]数矩形 几何
[BZOJ2338][HNOI2011]数矩形 题解:比较直观的做法就是枚举对角线,两个对角线能构成矩形当且仅当它们的长度和中点相同,然后用到结论:n个点构成的矩形不超过n^2.5个(不会证),所以两 ...
- uva 10733 The Colored Cubes<polya定理>
链接:http://uva.onlinejudge.org/external/107/10733.pdf 题意: N 种颜色可以涂成多少种立方体~ 思路: 使正六面体保持不变的运动群总共有: 1.不变 ...
- AbstractFactory Pattern
AbstractFactory模式用来解决这类问题:要创建一组相关或者相互依赖的对象. AbstractFactory Pattern结构图 实现: #ifndef _PRODUCT_H_ #defi ...
- Android在有存储卡和无存储卡情况下拍照后固定尺寸和压缩大小
我最近工作挺忙,距离上一次写博客转眼已经过了一个多月,每次学到和用到点新东西,其实都有分享的欲望,但奈何文笔太差,而一篇文章包括构思,排版,修改发布的时间最少要花费2个小时(这其中还不包括写完后未保存 ...
- Android项目中JNI技术生成并调用.so动态库实现详解
生成 jni方式有两种:一种是通过SWIG从C++代码生成过度的java代码:另一种是通过javah的方式从java代码自动生成过度的C++代码.两种方式下的步骤流程正好相反. 第一种方式:由于需要配 ...
- HDU2896 病毒侵袭 —— AC自动机
题目链接:https://vjudge.net/problem/HDU-2896 病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit ...
- [Vim 使用]vim 自动括号补全配置
打开Vim的配置文件,windows 上面的配置文件在vim 的安装目录下,_vimrc,使用记事本或vim打开 在下方加入如下代码 inoremap ( ()<ESC>i inorema ...