upc.2219: A^X mod P(打表 && 超越快速幂(in some ways))
2015-04-07 20:04
246 查看
2219: A^X mod P
Time Limit: 5 Sec Memory Limit: 128 MB Submit: 417 Solved: 68 [Submit][Status][Web Board]Description
It's easy for ACMer to calculate A^X mod P. Now given seven integers n, A, K, a, b, m, P, and a function f(x) which defined as following.f(x) = K, x = 1
f(x) = (a*f(x-1) + b)%m , x > 1
Now, Your task is to calculate
( A^(f(1)) + A^(f(2)) + A^(f(3)) + ...... + A^(f(n)) ) modular P.
Input
In the first line there is an integer T (1 < T <= 40), which indicates the number of test cases, and then T test cases follow. A test case contains seven integers n, A, K, a, b, m, P in one line.1 <= n <= 10^6
0 <= A, K, a, b <= 10^9
1 <= m, P <= 10^9
Output
For each case, the output format is “Case #c: ans”.c is the case number start from 1.
ans is the answer of this problem.
Sample Input
2 3 2 1 1 1 100 100 3 15 123 2 3 1000 107
Sample Output
Case #1: 14 Case #2: 63
HINT
Source
2013年山东省第四届ACM大学生程序设计竞赛#include<stdio.h> typedef long long ll ; int T ; int n, A, K, a, b, m, P ; int small [1 << 15 | 5] ; int big [1 << 15 | 5] ; int ans ; void solve () { int ret = 0 ; small[0] = 1 % P ; for (int i = 1 ; i < (1 << 15 | 5) ; i++) { small [i] = (ll) small[i - 1] * A % P ; } big[0] = 1 % P ; for (int i = 1 ; i < (1 << 15 ) ; i++) { big[i] = (ll) big[i - 1] * small [1 << 15] % P ; } while (n --) { ret += (ll) small [K & (1 << 15) - 1] * big [K >> 15] % P ; if (ret >= P) ret -= P ; K = ((ll) a * K + b) % m ; } printf ("Case #%d: %d\n" , ++ans , ret ) ; } int main () { //freopen ("a.txt" , "r" , stdin ); scanf ("%d" , &T) ; ans = 0 ; while (T--) { scanf ("%d%d%d%d%d%d%d" , &n , &A , &K , &a , &b , &m , &P) ; solve () ; } return 0 ; }
View Code
在求A^X 幂时,快速幂求的话,是O(10^6*log(n)*40) = O(10^9) 肯定会超时,
我们将X转化成 x = i*s + j。
举例来说:
100200= 100000 + 200 ; 如果我们要求A^100200 可以 转换成求 (A^100000 ) * (A^200).
所以我们只需要将 小的数 && 大的数 分别打表存在small[] , big[]中即可。
铭神给的代码里是用二进制表示的。题目里的数据是1 ~ 10^9。所以最大不会超过1 << 30 (10亿7千多万)
所以任何一个f(x) = j + ((1 << 15 ) * i ) 来表示
big[] : A^1 , A^2 , A^ 3 , A^ 4 …… A^s (用s表示 1 << 15)
small[] : A^(s * 1) , A^(s * 2) ,A^( s * 3) ,A^( s * 4) …… A^(s * s)
这样O(1)复杂度内就能找到 A^f(x)
这样每次求A^x,便可以通过这两个数组在O(1)的时间复杂度内求出来,这样时间复杂度就变成了O(10^6*40) = O(4*10^7)了
附代码:
相关文章推荐
- some cases about "const" in C Program
- Some of the best Open Source Project's in VC++ & MFC
- This collider has some illegal parameters. Choose 'Reset' in the component popup menu to fix it
- Decode Ways & String to Integer & Reverse Words in a String
- Some wrong ways to fix audio problems in Ubuntu
- Some of the best Open Source Project's in VC++ & MFC
- sdut2605 A^X mod P 山东省第四届ACM省赛(打表,快速幂模思想,哈希)
- SQL Error (1235): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
- This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
- PHP Storm Built In Server Doesn't Recognize mod_rewrite
- Some of the best Open Source Project's in VC++ & MFC
- Some of the best Open Source Project's in VC++ & MFC -- xiaojianpitt
- Some of the Best Open Source Project's in VC++ & MFC
- This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
- Some of the Best Open Source Project's in VC++ & MFC
- Some of the best Open Source Project's in VC++ & MFC
- Some of the best Open Source Project's in VC++ & MFC
- Some English website & Preparation for interview in the future
- sdut2605 A^X mod P 山东省第四届ACM省赛(打表,快速幂模思想,哈希)
- [原]sdut2605 A^X mod P 山东省第四届ACM省赛(打表,快速幂模思想,哈希)