【题目大意】

f(i)=((Af(i-1)+B)/(Cf(i-1)+D)) mod P。

给出f(0), A, B, C, D, P, n,求f(n)。

多组数据T<=1e4

n<=1e18, P <= 1e9, |f(0)|,|A|,|B|,|C|,|D| <= 1e9

保证任何时候存在逆元。

【题解】

首先我们有一种O(TP)的做法:找循环节。

考场上因为数据原因是可以AC的。。

# include <map>
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + ; # define RG register
# define ST static int A, B, C, D, mod, lm, rm;
ll f[], n;
map<int, int> mp; inline ll exgcd(ll a, ll b, ll &x, ll &y) {
if(b == ) {
x = ;
y = ;
return a;
}
exgcd(b, a%b, x, y);
ll t = x;
x = y;
y = t - (a/b)*y;
} inline ll getinv(ll n) {
ll x, y;
exgcd(n, (ll)mod, x, y);
x = (x%mod + mod) % mod;
return x;
} inline void sol() {
scanf("%lld%d%d%d%d%lld%d", &f[], &A, &B, &C, &D, &n, &mod);
A = (A+mod)%mod; B = (B+mod)%mod;
C = (C+mod)%mod; D = (D+mod)%mod;
mp.clear(); lm = rm = -; mp[f[]] = ;
for (int i=; i<=mod; ++i) {
f[i] = (A*f[i-] + B) % mod * getinv(C*f[i-] + D) % mod;
if(mp.find(f[i]) != mp.end()) {
lm = mp[f[i]], rm = i;
break;
}
mp[f[i]] = i;
}
// printf("%d %d\n", lm, rm);
assert(lm != - && rm != -);
if(n <= lm) printf("%lld\n", f[n]);
else printf("%lld\n", f[(n-lm)%(rm-lm)+lm]);
} int main() {
freopen("exercise.in", "r", stdin);
freopen("exercise.out", "w", stdout);
int T; cin >> T;
while(T--) sol();
return ;
}

标准做法是

f(i)=((Af(i-1)+B)/(Cf(i-1)+D))

f(i-1)=((Af(i-2)+B)/(Cf(i-2)+D))

那么

f(i)=((A^2+BC)f(i-2)+(AB+BD))//((AC+CD)f(i-2)+(CD+D^2))

相当于两个2*2的矩阵乘在一起。

那么矩乘即可。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + ; # define RG register
# define ST static int f0, A, B, C, D, mod, ans;
ll n; inline ll exgcd(ll a, ll b, ll &x, ll &y) {
if(b == ) {
x = ;
y = ;
return a;
}
exgcd(b, a%b, x, y);
ll t = x;
x = y;
y = t - (a/b)*y;
} inline int getinv(ll n) {
ll x, y;
exgcd(n, (ll)mod, x, y);
x = (x%mod + mod) % mod;
return x;
} struct matrix {
int a[][], n;
inline void set() {memset(a, , sizeof a);}
friend matrix operator * (matrix a, matrix b) {
matrix c; c.set();
for (int i=; i<=; ++i)
for (int j=; j<=; ++j)
for (int k=; k<=; ++k)
(c.a[i][j] += 1ll * a.a[i][k] * b.a[k][j] % mod) %= mod;
return c;
}
friend matrix operator ^ (matrix a, ll b) {
matrix c; c.set(); c.a[][] = c.a[][] = ;
while(b) {
if(b&) c=c*a;
a=a*a;
b >>= ;
}
return c;
}
}E; inline void sol() {
scanf("%d%d%d%d%d%lld%d", &f0, &A, &B, &C, &D, &n, &mod);
A = (A+mod) % mod; B = (B+mod) % mod; C = (C+mod) % mod; D = (D+mod) % mod;
E.set(); E.a[][] = A, E.a[][] = B, E.a[][] = C, E.a[][] = D;
E = E^n;
A = E.a[][], B = E.a[][], C = E.a[][], D = E.a[][];
ans = getinv((ll)C * f0 + D);
ans = 1ll * ans * (1ll * A * f0 % mod + B) % mod;
printf("%d\n", ans);
} int main() {
freopen("exercise.in", "r", stdin);
freopen("exercise.out", "w", stdout);
int T; cin >> T;
while(T--) sol();
return ;
}

校内训练0602 习题exercise的更多相关文章

  1. [4.14校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢. hzwer又出丧题虐人 4道noi....        很奇怪 每次黄学长出题总有一题我做过了. 嗯题目你们自己看看呗 好难解释 ----- ...

  2. [2017.4.7校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢. 报警啦.......hzwer又出丧题虐人啦..... 4道ctsc...有一道前几天做过了,一道傻逼哈希还wa了十几次,勉强过了3题..我好 ...

  3. [3.24校内训练赛by hzwer]

    来自FallDream的博客,未经允许,请勿转载,谢谢. ----------------------------------------------------------------------- ...

  4. 19_04_19校内训练[Game]

    题意 给出n,等概率地生成一个1~n的数列.现在有n个人从左到右站成一排,每个人拿有当前数列位置上的数字,并且一开始都不知道数字是多少(但知道n是多少).从左到右让每个人进行如下选择: 1.选择保留自 ...

  5. 19_04_02校内训练[deadline]

    题意 给出一个二分图,左边为A集合,右边为B集合,要求把A集合中每一个点染为黑白两色中的一种,B集合中的颜色已定.染色后对于原本相邻且颜色相同的点,建立新的二分图,即得到了两个新的二分图,它们是独立的 ...

  6. 平面图转对偶图&19_03_21校内训练 [Everfeel]

    对于每个平面图,都有唯一一个对偶图与之对应.若G‘是平面图G的对偶图,则满足: G'中每一条边的两个节点对应着G中有公共边的面,包括最外部无限大的面. 直观地讲,红色标出来的图就是蓝色标出的图的对偶图 ...

  7. fzyzojP3979 -- [校内训练20180914]魔法方阵

    原题见CF632F https://blog.csdn.net/Steaunk/article/details/80217764 这个比较神仙了 点边转化, 把max硬生生转化成了路径最大值,再考虑所 ...

  8. fzyzojP3580 -- [校内训练-互测20180315]小基的高智商测试

    题目还有一个条件是,x>y的y只会出现一次(每个数直接大于它的只有一个) n<=5000 是[HNOI2015]实验比较 的加强版 g(i,j,k)其实可以递推:g(i,j,k)=g(i- ...

  9. fzyzojP3372 -- [校内训练20171124]博弈问题

    对于每个点都要答案 还是异或 trie树合并石锤了 朴素枚举是O(n^2*17)的 怎么办呢? 我们发现合并的时候,一些部分的trie的子树还是不变的 改变的部分也就是合并的复杂度可以接受 鉴于大部分 ...

随机推荐

  1. php扩展开发-面向对象

    在zval变量里IS_OBJECT类型使用zend_object_value来保存变量的,我们看一下他的具体结果. typedef struct _zend_object_value { zend_o ...

  2. JDK学习---深入理解java中的HashMap、HashSet底层实现

    本文参考资料: 1.<大话数据结构> 2.http://www.cnblogs.com/dassmeta/p/5338955.html 3.http://www.cnblogs.com/d ...

  3. sql语句(Oracle和sqlserver)

    查询表的首句:(Oracle) select * from (select a.*, rownum as rn from tab_name a order by col )where rn = 1 o ...

  4. 笔记-docker-1

    笔记-docker-1 1.      简介 1.1.    什么是Docker? Docker 是世界领先的软件容器平台.开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问 ...

  5. GPIO基础知识

    STM32 GPIO入门知识 GPIO是什么? 通用输入输出端口,可以做输入,也可以做输出.GPIO端口可通过程序配置成输入或输出. 引脚和GPIO的区别和联系 STM32的引脚中,有部分是做GPIO ...

  6. PHP.24-TP框架商城应用实例-后台1-添加商品功能、钩子函数、在线编辑器、过滤XSS、上传图片并生成缩略图

    添加商品功能 1.创建商品控制器[C] /www.test.com/shop/Admin/Controller/GoodsController.class.php <?php namespace ...

  7. linux 多播

    1.概念 单播是用于两个主机之间传送数据,广播是一个主机对局域网内的所有主机发送数据.而多播,又称为组播,它是对一组特定的主机通信.将网络上同一类型 业务逻辑上分组,只和组内的成员通信,其它主机没有加 ...

  8. dealloc时取weakself引起崩溃

    今天无意这中遇到一个奇怪的崩溃,先上引起崩溃的代码: - (void)dealloc { __weak __typeof(self)weak_self = self; NSLog(@"%@& ...

  9. hasOne

    public boolean hasOne(int n) { int lastdigit=0; while( n >0 ){ lastdigit=(n % 10); if(lastdigit== ...

  10. 每天一个Linux命令(7):pwd命令

    pwd命令以绝对路径的方式显示用户当前工作目录. 语法 pwd(选项) 选项 --help:显示帮助信息: --version:显示版本信息. 实例 [root@localhost ~]# pwd / ...