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 ...
随机推荐
- Effective Java - [2. 创建与销毁对象]
让对象的创建与销毁在掌控中. Item 1: 使用静态工厂方法而非使用构造函数 public static Boolean valueOf(boolean b) { return b ? Boolea ...
- Activiti实战
说实话,接触Activiti已经是3年前的事情,那时候组里想做一个流程自动化的application,并且记录用户点击.做单量等.第一次听说Activiti,感觉挺好奇的,遂看了下相关的文档跟同事的代 ...
- 将txt文件数据存入excel表格
前言 最近使用Appium自动化在测试设备配网的情况,需要记录每次成功与否和耗时时间. 由于App不是很稳定,执行一段时间会奔溃,因此数据只能通过追加的形式写入到txt文件. 实现过程 存储在txt文 ...
- Oracle中如何进行进制转换(2进制,10进制,16进制)
1.16进制转换为10进制 可以通过to_number函数实现 SQL> select to_number('19f','xxx') from dual; TO_NUMBER('19F','XX ...
- ACM-BFS之Open the Lock——hdu1195(双向BFS)
这道题的0基础版本号,暴力BFS及题目详情请戳:http://blog.csdn.net/lttree/article/details/24658031 上回书说道,要用双向BFS来尝试一下. 最终A ...
- 3932: [CQOI2015]任务查询系统
3932: [CQOI2015]任务查询系统 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2559 Solved: 819[Submit][Sta ...
- jsp页面中文乱码解决方案
一.JSP页面中文乱码 在JSP页面中,中文显示乱码有两种情况:一种是HTML中的中文乱码,另一种是在JSP中动态输出的中文乱码. 先看一个JSP程序: <%@ page language=&q ...
- lateral inhibition
http://www.indiana.edu/~p1013447/dictionary/lat_i.htm [This means that neighboring visual neurons re ...
- @GetMapping和@PostMapping接收参数的格式
一.1.使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面 若返回json等内容到页面,则需要加@ResponseBody注解 ...
- 青岛理工交流赛 H题 素数间隙
13110581088注销 素数间隙 Time Limit: 1000MS Memory limit: 262144K 题目描述 Neko猫是一个很喜欢玩数字游戏的会说话的肥猫,经常会想到很多很好玩的 ...