薛XX后代的IQ CSU1597【循环节】或【快速幂】

薛先生想改变后代的IQ,为此他发明了一种药,这种药有三种属性:A, B,
P。他父亲的智商为X,薛先生的智商为Y,用了这种药之后,薛先生的孩子的智商就可以变为(AX+BY) mod P。后代的智商以此类推。

现在给定X和Y,还有药的属性A、B和P,现在他想知道他的N代子孙的IQ(儿子是第一代,孙子是第二代)。

Input
第一行包含一个整数T(T<=100),表示数据组数 每组数据只有一行,包含六个整数X,Y,A,B,P,N(1 ≤ X, Y ≤ 300,1 ≤ A, B ≤ 30, 1≤ P ≤ 300 , 1 ≤ N < 1000000000),含义如题目所述
Output
针对每组数据,输出第N代子孙的智商。

Sample Input

4
180 80 1 1 190 1 
189 83 2 2 190 1 
189 83 1 1 190 2 
172 73 23 19 273 9999

Sample Output

70 
164 
165 
233

【思路】
本题有两种解法:

  1. 循环节
    由题显然可以看出,P在1-300之间,则结果一定会在1-90000之间出现循环节,注意是连续的两组数据要同时和之前出现的一组数据相同,才被确认为出现了循环节。另外,循环节不一定是从0,1开始,可能呈6字形,也即从数据的中间开始出现循环,八戒影院这种情况一定要考虑。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 90009;
int ans[maxn+2];
int vis[303][303];

int main()
{
    int t;
    scanf("%d", &t);
    int x, y, a, b, p, n;
    while(t--){
        memset(vis, -1, sizeof(vis));
        scanf("%d%d%d%d%d%d", &x, &y, &a, &b, &p, &n);
        ans[0] = y;
        ans[1] = (a * x + b * y) % p;
        vis[ans[0]][ans[1]] = 0;
        int start;
        int circle;
        for(int i = 2; i < maxn; i++){
            ans[i] = (a * ans[i-2] + b * ans[i-1]) % p;
            if(vis[ans[i-1]][ans[i]] != -1){
                start = vis[ans[i-1]][ans[i]];
                circle = i - 1 - start;
                break;
            }
            else
                vis[ans[i-1]][ans[i]] = i-1;
        }
        cout << ans[start + (n - start) % circle] << endl;
    }
    return 0;
}
  1. 快速幂
    这种类似斐波那契的数据类型,可以用快速幂来解决。要注意的是初始矩阵的初始化不能出错。然后再写一个矩乘函数就行了。

代码如下:

#include<cstdio>
#include<iostream>
#include<string>
#include<set>
using namespace std;
typedef long long LL;
int mod;
int x, y, p, q;
struct Node{LL m[3][3];};

void Init(Node &t, Node &a){
    t.m[1][1] = y;
    t.m[2][2] = 0;
    t.m[1][2] = x;
    t.m[2][1] = 0;
    a.m[1][1] = q;
    a.m[1][2] = 1;
    a.m[2][1] = p;
    a.m[2][2] = 0;
}

Node mul(Node a, Node b){
    Node tem;
    tem.m[1][1] = (a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1]) % mod;
    tem.m[1][2] = (a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2]) % mod;
    tem.m[2][1] = (a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1]) % mod;
    tem.m[2][2] = (a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2]) % mod;
    return tem;
}

int main (){
    int n;
    int tim;
    scanf("%d", &tim);
    Node t, a;
    while(tim--){
        scanf("%d%d%d%d%d%d",www.rcsx.org &x, &y, &p, &q, &mod, &n);
        Init(t, a);
        while(n){
            if(n&1) t = mul(t,a);
            a = mul(a, a);
            n >>= 1;
        }
        cout << t.m[1][1] % mod << endl;
    }

    return 0;
}
时间: 2025-01-08 22:58:39

薛XX后代的IQ CSU1597【循环节】或【快速幂】的相关文章

CSU 1597 薛XX后代的IQ

Description 薛XX的低IQ是个令人头疼的问题,他的队友深受其害.幸运的是,薛XX非常有钱,所以他买了一些可以提高他的后代的IQ的药.这种药有三个属性,A,B和P.当薛XX使用这种药的时候,他的基因会发生变化,所以他的儿子的IQ也会跟着变化.假设薛XX的父亲的IQ为X,薛XX自己的IQ为Y,那么薛XX的儿子的IQ为(A*X+B*Y) mod P.薛XX的孙子的IQ依次类推.现在给定X和Y,还有药的属性A.B和P,现在他想知道他的N代子孙的IQ(儿子是第一代,孙子是第二代). Input

Brute-force Algorithm HDU - 3221(指数循环节 矩阵快速幂)

水题一道 推一下就是 f[n] = f[n - 1] + f[n - 2] 发现n很大 所以用矩阵快速幂就好了 还有P很大  那就指数循环节 一定要注意   这个条件 #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <cctype> #include <set> #incl

hdu 5895 Mathematician QSC 指数循环节+矩阵快速幂

Mathematician QSC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description QSC dream of becoming a mathematician, he believes that everything in this world has a mathematical law. Through unremitting e

LA 3704细胞自动机——循环矩阵&amp;&amp;矩阵快速幂

题目 一个细胞自动机包含 $n$ 个格子,每个格子的取值为 $0 \sim m-1$.给定距离 $d$,则每次操作是将每个格子的值变为到它的距离不超过 $d$ 的所有格子的在操作之前的值的和除以 $m$ 的余数.给出 $n, m, d, k$ 和自动机各个格子的初始值.你的任务是计算 $k$ 次操作以后各格子的值.($1 \leq n\leq 500, 1 \leq m\leq 10^6, 0 \leq d\leq n/2, 1\leq k\leq 10^7$). 分析 如果我们把 $t$ 次操

UVA 11582 Colossal Fibonacci Numbers!(循环节打表+幂取模)

题目链接:https://cn.vjudge.net/problem/UVA-11582 1 /* 2 问题 3 输入a,b,n(0<a,b<2^64(a and bwill not both be zero) and 1<n<1000) 4 计算并输出f(a^b)%n的结果 5 其中f(i)是斐波那契数列 6 7 解题思路 8 所有的结果都是f(i)对n取模,不妨设F(i)=f(i)%n.不难发现当F(i),F(i+1)出现重复的时候,整个序列就开始出现重复. 9 10 所以设周

HDU 5895 Mathematician QSC(矩阵乘法+循环节降幂+除法取模小技巧+快速幂)

传送门:HDU 5895 Mathematician QSC 这是一篇很好的题解,我想讲的他基本都讲了http://blog.csdn.net/queuelovestack/article/details/52577212 [分析]一开始想简单了,对于a^x mod p这种形式的直接用欧拉定理的数论定理降幂了 结果可想而知,肯定错,因为题目并没有保证gcd(x,s+1)=1,而欧拉定理的数论定理是明确规定的 所以得另谋出路 那么网上提供了一种指数循环节降幂的方法 具体证明可以自行从网上找一找 有

1/n循环节长度

/* * 求1/i的循环节长度的最大值,i<=n */ const int MAXN = 1005; int res[MAXN]; // 循环节长度 int main() { memset(res, 0, sizeof(res)); int i, temp, j, n; for (temp = 1; temp <= 1000; temp++) { i = temp; while (i % 2 == 0) { i /= 2; } while (i % 5 == 0) { i /= 5; } n

循环节长度

两个整数做除法,有时会产生循环小数,其循环部分称为:循环节. 比如,11/13=6=>0.846153846153.....  其循环节为[846153] 共有6位. 下面的方法,可以求出循环节的长度. 请仔细阅读代码,并填写划线部分缺少的代码. public static int f(int n, int m) { n = n % m;   Vector v = new Vector(); for(;;) { v.add(n); n *= 10; n = n % m; if(n==0) ret

hud5451_求循环节加矩阵快速幂

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5451 题目描述: 对于,给出x和mod,求y向下取整后取余mod的值为多少? 找循环节解析链接:http://blog.csdn.net/ACdreamers/article/details/25616461 裸题链接:http://blog.csdn.net/chenzhenyu123456/article/details/48529039 1 #include <algorithm> 2 #i