虽说是一道裸题,但还是让小C学到了一点姿势的。
Description
给定一个长度为n的数组w,模数m和询问次数q,每次询问给定l,r,求:
对m取模的值。
Input
第一行两个整数n,m,表示数组长度和模数。
接下来一行n个数,表示w数组。
接下来一行一个整数q,表示询问次数。
接下来q行,每行两个整数l,r,表示一次询问。
Output
对于每次询问,输出一行一个整数表示答案。
Sample Input
6 1000000000
1 2 2 3 3 3
8
1 1
1 6
2 2
2 3
2 4
4 4
4 5
4 6
Sample Output
1
1
2
4
256
3
27
597484987
HINT
1 ≤ n ≤ 105,1 ≤ m ≤ 109,1 ≤ wi ≤ 109,1 ≤ q ≤ 105,1 ≤ l ≤ r ≤ n。
Solution
看到这么清奇的式子,你大概会第一时间想到降幂大法吧?
先说说扩展欧拉定理,对于任意正整数a,b,p:
所以假设堆叠的幂次足够大,那么式子就可以转化为:
已知p经过至多2log次phi就会变成1。
所以递归求解,至多走到2log层模数就会变成1,所以返回0就行。
所以这道题就非常显然了,首先预处理出m的所有phi,对于每个询问,从l开始直接递归暴力,直到模数为1时返回。
还有一个问题,在求a^b%p的时候,怎么比较b和phi(p)的大小呢?
一种思路就是暴力计算a的后log项的值,注意还要特判1的情况,但这样写起来确实麻烦。
当然,有一种非常精妙的取模写法:
int modulo(ll x,int mod) {return x
这是在做什么呢?这就是在比较b和phi(p)的大小,如果b 然后原式就变成了这样: 这样做看上去漏洞百出,可能的情况是,原本我们要计算,其中大等于。 是否有这种可能呢? 其实就相当于判断是否有可能成立,我们可以发现,当a>2时式子是不可能成立的。 有可能。 当且仅当p=6时,不等式成立。 然而6有什么特殊的性质呢? 我们发现phi(x)=6只有两个解:x=7或x=9。 当x=9时,若gcd(a,9)=1,则,影响同上; 若gcd(a,9)≠1,因为,所以, 又因为一定有,所以一定有 , 所以一定有,所以少一个对于答案是没有影响的。 所以综上,我们就证明了该算法的正确性。 时间复杂度。 打Codeforces的时候正纳闷这种情况该怎么处理,却发现大佬们清一色都是这么写的。 小C觉得自己的证明蠢得不行啊…… 如果读者有更直观的证明该算法的正确性的方法请务必告诉小C。#include
Last Word