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 ...
随机推荐
- Python自动生成文章
为了应付某些情况,需要做17份记录.虽然不很重要,但是17份完全雷同也不很好.大体看了一下,此记录大致分为四段.于是决定每段提供四种选项,每段四选一,拼凑成四段文字,存成一个文件.文件名就叫“XX记录 ...
- ios开发动物园管理 继承多态的实现
// // main.m // 继承 // // #import <Foundation/Foundation.h> #import "Animal.h" #impor ...
- C++算法之 一句话推断一个整数是不是2 的整数次方
思路:一个整数假设是2的整数次方,那么它的二进制表示中有且仅仅有一位是1,而其它全部位都是0.把这个整数与这个整数减去1之后进行与运算.那么这个整数其中唯一的 1会变为0,这个整数也变为0: 代码: ...
- 美化你的APP——从Toolbar開始
Toolbar是什么 Toolbar是Google在Android 5.0中推出的一款替代ActionBar的View.ActionBar必须得作为Activity内容的一部分,而Toolbar能够放 ...
- BAT网络运维常见面试题目总结
BAT常见面试题目总结 Author:Danbo 2015-7-11 TCP/IP详解鸟哥Linux的书网络安全ping的原理make的过程文件有哪些类型各种Linux发行版的区别.有关suid的作用 ...
- 使用libcurl进行HTTP GET操作
Working example how to do a GET request with libcurl and save it to a string variable for future use ...
- struts2 小例子(教训篇)
学了一阵子的struts2了,到了最后,想自己写个小程序,发现最简单的配置文件都 竟然能弄错,是我这几天睡眠不足么.怎么可能,爱好这门的,怎么会这样.这样真的很伤心啊.小小心灵受不了这种打击啊.... ...
- hdu-5744 Keep On Movin(思维)
题目链接: Keep On Movin Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Oth ...
- java实现EXCEL数据导入到数据库中的格式问题的解决
之前作为项目甲方,加之java接触不多,在java web开发方面都是打下手的份. 对于EXCEL数据导入到数据库这个问题一直老是出现格式原因而导入失败也是未免惆怅,开发团队也是只说回去检查一下格式. ...
- 合并多个cv::Mat类型,即合并多个图片的接口
1. cv::Mat get_merage_image(cv::Mat cur_frame) { cv::Mat image_one=cur_frame; cv::Mat image_two=cur_ ...