首页 > 代码库 > 【快速幂+中等难度】Calculation 哈工大HITOJ2901
【快速幂+中等难度】Calculation 哈工大HITOJ2901
这些天好颓啊。。都没有A题,只是各种等着填的坑。。简直、、
这道题。。。。其实是快速幂模板题。。为了学习矩阵快速幂,顺手复习下快速幂。。。
哈工大的OJ其实还挺友好的。速度也快。。赞一个。。
翻译
给你两个数A,B,要你求(1b + 2b + ... + ab) 这个式子mod a的结果。(b是奇数)
每行一组数据
(我以下的代码和解释都是用大写的A,B来代替原题小写a,b,代码中的小写a只是一个类似tmp的东西)
原题
http://acm.hit.edu.cn/hoj/problem/view?id=2901
Given two integers a and b, you are to calculate the value of the following expression: (1b + 2b + ... + ab) modulo a.
Note that b is an odd number.
Input specifications
Each line of input consists of two integers a and b (1≤a≤1000000000, 1≤b≤1000000000) respectively.
Output specifications
For each case of input, you should output a single line, containing the value of the expression above.
Sample Input
1 12 1
Sample Output
0
1
思路
快速幂模板题。
中等难度是因为有一个人类根本YY不出来的优化:(我偷偷看了看题解。。)
根据二项式展开,发现 [ c^b+(a-c)^b ] % a = 0 ,所以有:
若a为奇数,答案为0,若a为偶数,答案为a/2的b次方(快速幂) 还要%a。。
下面给个人类的推导过程:
一定是发现了什么不得了的东西:当我们把第i项和第A-i项的结果相加,刚好会被A整除。。所以。。
只有偶数的一半那个(如上图12的一半6)只有两个自己相加。。而实际上没有两个同样的项,那么我们要输出的就是它的快速幂结果。。
所以:奇数:0,偶数:((A/2)^B)%A;
这样我们成功把复杂度降到了O(n)左右。。(如果出题人太坑也没办法,事实证明没有这么坑)
这里以上的证明都是针对B为奇数的特例,如果B为偶数则以上式子均不适用
(如果A,B均为偶数,则第i项与第A-i+1项的和会呈现对称分布。。(或者说第i项与第A-i项的和们最后一项是0,前面的呈现对称分布),
而若A为奇数,B为偶数,第i项与第A-i(+1)项的和会很奇怪。。我也没找到规律。。)
注意
一个数的奇偶性可以用&1来判断,即若(P&1)==1则表示P为奇数,若(P&1)==0则表示P为偶数
当然,这只是一个优化常数的方法。。如果没有把握还是用%2吧。。
代码
/*http://acm.hit.edu.cn/hoj/problem/view?id=2901*/#include<iostream>#include<cstdlib>#include<cstdio>#include<cmath>#include<cstring>using namespace std;long long A,B;inline int read(){ long long x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f;}struct pointer{ long long AA,BB;};long long Matrix_multiplication(long long a, long long n){ long long ret = 1; while(n) { if(n&1) ret = (ret*a)%A; a = (a*a)%A; n >>= 1; } return ret;}int main(){ long long times,ans; while( cin>>A>>B ) { ans=0; if ((A&1)==0) { ans=Matrix_multiplication(A/2,B); ans%=A; } else { ans=0; } cout<<ans<<endl;} return 0;}
结果