CSU - 1752 童话故事生成器

来源:互联网 发布:ubuntu 16.04 飞秋 编辑:程序博客网 时间:2024/04/27 23:14

题目:

Description

机器人宝宝又要听机器人妈妈讲故事了。由于机器人宝宝的记忆力超常,所以机器人妈妈每天讲的故事都要接在上一个故事后面。假设机器人妈妈讲的第一个故事是X1,那么第二个是X2,i个是Xi= (a * Xi-1 + b) % c + 1。现在你希望知道第n天机器人妈妈讲的故事是什么。

Input

第一行输入一个整数 T (1 <= T <= 100) 表示有T组数据;

接下来每一行输入5个整数X1(1<=X1<=1000000) , a(1<=a<=1000000) , b(1<=b<=1000000) , c(1<=c<=1000000) , n(2<=n<=1e18);

Output

求第n天机器人妈妈讲的故事是什么;

Sample Input

21 1 1 1000 2394706 314559 674595 559832 4431920000000001

Sample Output

3554658

首先我们注意到,Xi= (a * Xi-1 + b) % c + 1这个式子的取值范围是1到c

也给我们带来了很大的方便,只需要求出与Xn mod c同余的任何一个数,即可得到Xn

所以上式可以这么写:Xia * Xi-1 + b+1 (mod c)

所以,XiX1*a^(n-1)+(b+1)*(a^(n-2)+......+a^2+a+1) (mod c)

所以,Xn=(X1*mi_a_c(n - 1)+(b+1)*sum(n-2)-1)%c+1

感觉一点破绽都没有,可是就是WA。

WA的代码:

#include<iostream>using namespace std;long long t, x, a, b, c;long long mi_a_c(long long n){if (n == 0)return 1;long long s = mi_a_c(n / 2);s = s*s;if (n % 2)s *= a;return s%c;}long long  sum(long long n){if (n == 0)return 1;long long s = sum(n / 2);s += (s + n % 2 - 1)*mi_a_c((n + 1) / 2);return s%c;}int main(){long long n;cin >> t;while (t--){cin >> x >> a >> b >> c >> n;x *= mi_a_c(n - 1);x += (b + 1)*sum(n - 2);cout << (x - 1) % c + 1 << endl;}return 0;}

没办法,只好单独对2个函数进行测试,还真发现了问题所在。

原来,sum函数中的s += (s + n % 2 - 1)*mi_a_c((n + 1) / 2);这一句有问题

s + n % 2 - 1可能会得到-1,所以把s + n % 2 - 1改成s + n % 2 - 1+c就AC 了。

然后我又用矩阵快速幂做了一遍,也AC了。


代码:

#include<iostream>using namespace std;long long t, x, a, b, c;long long a11, a12, a21, a22;void mi(long long n){if (n == 0){a11 = a22 = 1;a12 = a21 = 0;return;}mi(n / 2);long long b11 = (a11*a11 + a12*a21) % c, b12 = (a11*a12 + a12*a22) % c;long long b21 = (a11*a21 + a21*a22) % c, b22 = (a21*a12 + a22*a22) % c;a11 = b11, a12 = b12, a21 = b21, a22 = b22;if (n % 2){a12 += a11, a22 += a21;a11 *= a, a21 *= a;a11 %= c, a12 %= c, a21 %= c, a22 %= c;}}int main(){long long n;cin >> t;while (t--){cin >> x >> a >> b >> c >> n;mi(n-1);cout << (x*a11 + (b+1)*a12 - 1) % c + 1 << endl;}return 0;}

2个代码的效率是不一样的。

后面的矩阵快速幂比较快,是log n

前面的快速幂是log n + log (n/2) +log (n/4) +......=(log n)^2 / 2

不过常数不一样,矩阵是2*2的,所以后面的是4* log n,前面的是(log n)^2 / 2

1 0
原创粉丝点击