hdu 2814 Interesting Fibonacci

来源:互联网 发布:天天特价淘宝网太阳镜 编辑:程序博客网 时间:2024/05/15 10:09

题目:hdu 2814 Interesting Fibonacci

题意:求F(a^b)^(F(a^b) ^ (n-1))%c  (F(n)表示斐波那契数列,1<=c<=300,a,b,n都是2^64的数,用unsigned long long存)

思路:指数循环节和斐波那契数列循环节

我是不会跟你说这题我WA,TLE,RE了二三十次了。。。然后足足AC了七遍。。

F(n)%c 的情况,根据斐波那契数列的循环节求出来,做法跟12年四川现场赛那题一样。

式子中存在两个F(a^b) ,对于第一个,求对于mod c的循环节,第二个根据指数循环节,求mod phi(c)的循环节,然后其他就是乱七八糟的求快速幂,求斐波那契数列。

这题,TLE若干次之后,发现因为c的范围只有300,所以我们可以先预处理300以内数字的循环节。

然后,经历了若干次RE,原因是除0了(我除你妹的0,我压根就没粗线过0)。

意外的将题目数据改成17 18446744073709551615 1998 2程序直接跪了,看来问题在于 mod 2 的那,找了下别人的代码,试了这组数据,照样跪了,但是为喵别人能AC 呢 (之后我AC的代码输出的答案是 1)

所以呢,在经历无数次WA之后,貌似找到问题所在了,模1的情况答案输出当然是0,模2的暂时不知道,想一想欧拉值等于1的只有2,所以当c=2的时候,F的幂的部分就mod 1直接等于0,所以不管底数多少,答案就是1了,解释了我刚才说的样例。

然后对于前面的预处理 smod[1]=1 这个得加上(虽然我不知道什么时候会出现这种数据,但是不加这句话,就是会RE)


#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <iostream>using namespace std;typedef unsigned __int64 LL;struct Matrix{LL m[3][3];}E, D;LL Pow(LL a, LL b, LL mod){LL ans = 1;while (b){if (b & 1){b--;ans = (ans*a)%mod;}else{b /= 2;a = (a*a)%mod;}}return ans;}void init(){for (int i = 1; i <= 2; i++)for (int j = 1; j <= 2; j++){D.m[i][j] = 1;E.m[i][j] = (i == j);}D.m[2][2] = 0;}Matrix Multi(Matrix A, Matrix B, LL mod){Matrix ans;for (int i = 1; i <= 2; i++)for (int j = 1; j <= 2; j++){ans.m[i][j] = 0;for (int k = 1; k <= 2; k++)ans.m[i][j] = (ans.m[i][j] + A.m[i][k] * B.m[k][j])%mod;}return ans;}Matrix Pow(Matrix A, LL k, LL mod){Matrix ans = E;while (k){if (k & 1){k--;ans = Multi(ans, A, mod);}else{k /= 2;A = Multi(A, A, mod);}}return ans;}LL Fib(LL n, LL mod){return Pow(D, n, mod).m[2][1];}long long euler(long long x){long long i, res = x;for (i = 2; i*i <= x; i++)if (x%i == 0){res = res / i*(i - 1);while (x%i == 0)x /= i;}if (x > 1)res = res / x*(x - 1);return res;}LL s_mod(LL n){LL a1 = 0, a2 = 1, a3 = 1, tmp, ans = 1;while (a2 != 0 || a3 != 1){ans++;tmp = (a2 + a3)%n;a2 = a3;a3 = tmp;}return ans;}LL smod[305];int main(){init();smod[1] = 1;for (int i = 2; i <= 300; i++)smod[i] = s_mod(i);LL a, b, n;int c;int t;scanf("%d", &t);LL mod1, mod2, tmp, cnt, ans, eul;for (int cas = 1; cas <= t; cas++){scanf("%I64u%I64u%I64u%d", &a, &b, &n, &c);if (c == 1){printf("Case %d: 0\n", cas);continue;}mod1 = smod[c];eul = euler(c);mod2 = smod[eul];tmp = Pow(a%mod1, b, mod1);tmp = Fib(tmp, c);cnt = Pow(a%mod2, b, mod2);cnt = Fib(cnt, eul);cnt = Pow(cnt, n - 1, eul);cnt += eul;ans = Pow(tmp, cnt, c);printf("Case %d: %I64u\n", cas, ans);}//system("pause");return 0;}