开始玩矩阵了!先来一道入门题![SDOI2008]递归数列
[SDOI2008]递归数列
题目描述
一个由自然数组成的数列按下式定义:
对于i <= k:ai = bi
对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k
其中bj 和 cj (1<=j<=k)是给定的自然数。写一个程序,给定自然数m <= n, 计算am + am+1 + am+2 + ... + an, 并输出它除以给定自然数p的余数的值。
输入输出格式
输入格式:
输入文件spp.in由四行组成。
第一行是一个自然数k。
第二行包含k个自然数b1, b2,...,bk。
第三行包含k个自然数c1, c2,...,ck。
第四行包含三个自然数m, n, p。
输出格式:
输出文件spp.out仅包含一行:一个正整数,表示(am + am+1 + am+2 + ... + an) mod p的值。
输入输出样例
- 2
- 1 1
- 1 1
- 2 10 1000003
- 142
说明
对于100%的测试数据:
1<= k <=15
1 <= m <= n <= 1018
对于20%的测试数据:
1<= k <=15
1 <= m <= n <= 106
对于30%的测试数据:
k=1 1 <= m <= n <= 1018
对于所有测试数据:
0<= b1, b2,... bk, c1, c2,..., ck<=109
1 <= p <= 108
挺水的一道题,推出了矩阵,然后前缀和搞搞也就简单了;
矩阵如下:
S[n] |
b[n] |
b[n-1] |
... |
b[n-k+1] |
=
1 | c[1] | ... | c[k-1] | c[k] |
0 | c[1] | ... | c[k-1] | c[k] |
0 | 1 | ... | 0 | 0 |
0 | 0 | ... | 0 | 0 |
0 | 0 | ... | 1 | 0 |
*
S[n-1] |
b[n-1] |
b[n-2] |
... |
b[n-k+1] |
- #include<bits/stdc++.h>
- #define ll long long
- #define maxn 20
- using namespace std;
- ll k,b[maxn],c[maxn],n,m,p,tot;
- struct mat{
- ll x,y;
- ll s[maxn][maxn];
- };
- mat operator *(mat a,mat b)
- {
- mat c;
- c.x = a.x;
- c.y = b.y;
- memset(c.s,,sizeof(c.s));
- for(ll i=;i<=a.x;i++)
- for(ll j=;j<=b.y;j++)
- for(ll k=;k<=b.x;k++)
- c.s[i][j] = (c.s[i][j] + a.s[i][k] * b.s[k][j] % p) % p;
- return c;
- }
- mat ksm(mat a,ll ci)
- {
- mat ans;
- memset(ans.s,,sizeof(ans.s));
- ans.x = ans.y = a.x;
- for(ll i=;i<=ans.x;i++)
- ans.s[i][i] = ;
- while(ci)
- {
- if(ci & ) ans = ans * a;
- a = a * a;
- ci >>= ;
- }
- return ans;
- }
- ll find(ll num)
- {
- if(num <= k)
- {
- ll ans = ;
- for(ll i=;i<=num;i++) ans += b[i],ans %= p;
- return ans % p;
- }
- mat ans;
- memset(ans.s,,sizeof(ans.s));
- ans.x = ans.y = k + ;
- for(ll i=;i<=k+;i++)
- ans.s[][i] = ans.s[][i] = c[i - ];
- ans.s[][] = ;
- for(ll i=;i<=k;i++)
- ans.s[i + ][i] = ;
- ans = ksm(ans , num - k);
- mat right;
- memset(right.s,,sizeof(right.s));
- right.x = k + ;
- right.y = ;
- for(ll i=;i<=k+;i++)
- right.s[i][] = b[k + - i];
- right.s[][] = tot;
- right = ans * right;
- return right.s[][];
- }
- int main(){
- cin >> k;
- for(ll i=;i<=k;i++) scanf("%d",&b[i]),tot += b[i];
- for(ll i=;i<=k;i++) scanf("%d",&c[i]);
- cin >> m >> n >> p;
- cout << (find(n) - find(m - ) + p) % p;
- }
开始玩矩阵了!先来一道入门题![SDOI2008]递归数列的更多相关文章
- BZOJ 3231: [Sdoi2008]递归数列( 矩阵快速幂 )
矩阵乘法裸题..差分一下然后用矩阵乘法+快速幂就可以了. ----------------------------------------------------------------------- ...
- BZOJ_3231_[Sdoi2008]递归数列_矩阵乘法
BZOJ_3231_[Sdoi2008]递归数列_矩阵乘法 Description 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1a ...
- 可恶!学了这么久的LCA,联考的题目却是LCA+树形DP!!!可恶|!!!这几天想学学树形DP吧!先来一道入门题HDU 1520 Anniversary party
题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...
- [bzoj3231][SDOI2008]递归数列——矩阵乘法
题目大意: 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj和 cj ...
- 【bzoj3231】[Sdoi2008]递归数列 矩阵乘法+快速幂
题目描述 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj和 cj ...
- [luoguP2461] [SDOI2008]递归数列(DP + 矩阵优化)
传送门 本题主要是构造矩阵,我们只需要把那一段式子看成两个前缀和相减, 然后就直接矩阵连乘. 直接对那个k+1阶矩阵快速幂即可,注意初始化矩阵为单位矩阵,即主对角线(左上到右下)都为1其他都为0. 另 ...
- bzoj 3231: [Sdoi2008]递归数列【矩阵乘法】
今天真是莫名石乐志 一眼矩阵乘法,但是这个矩阵的建立还是挺有意思的,就是把sum再开一列,建成大概这样 然后记!得!开!long!long!! #include<iostream> #in ...
- [luogu2461 SDOI2008] 递归数列 (矩阵乘法)
传送门 Description 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai- ...
- P2461 [SDOI2008]递归数列 矩阵乘法+构造
还好$QwQ$ 思路:矩阵快速幂 提交:1次 题解: 如图: 注意$n,m$如果小于$k$就不要快速幂了,直接算就行... #include<cstdio> #include<ios ...
随机推荐
- 获取win10壁纸
执行命令会将所有壁纸拷贝到桌面上的wallpaper文件夹内 bat xcopy %LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryMa ...
- mysql源码包安装
一.准备编译环境 # yum -y install ncurses ncurses-devel openssl-devel bison gcc gcc-c++ make cmake # wget ht ...
- 数据库之DML
1.表的有关操作: 1.1.表的创建格式: CREATE TABLE IF NOT EXISTS 表名(属性1 类型,属性2 类型,....,属性n 类型):# 标记部分表示可以省略 1.2.表的修改 ...
- Python示例-Logging
logging.ini日志配置文件内容示例: [loggers] keys=root,demo [handlers] keys=consoleHandler,timedRotatingFileHand ...
- JavaScript Return Object.Type
var getType = function(obj) { if (obj == null) { return String(obj); } return typeof obj === 'object ...
- Linux下安装tomcat与配置
准备工作:将下载好的tomcat 9.0上传到自己的阿里云服务器(推荐根目录下) 附下载地址:https://archive.apache.org/dist/tomcat/tomcat-9/v9.0. ...
- 区间gcd
http://codeforces.com/problemset/problem/914/D 题意:给你n个数,两种操作:1.询问区间[l,r]在至多一次修改一个数的条件下区间gcd是否等于x. 2. ...
- 最少多少人说谎(dp)
https://ac.nowcoder.com/acm/contest/1168/H 题意:n个学生,邓志聪想知道这些学生的考试情况,于是一个一个叫这些学生叫去办公室问他们,但是有些学生并没有讲真话, ...
- Nginx工作机制
Nginx分为单工作进程和多工作进程两种模式.通常采用1个master+多个worker进程配合异步非阻塞的工作机制.master进程主要负责管理自身和下属的worker进程,worker负责处理请求 ...
- 列表、元组和range
小知识点 s = " 5 " print(int(s)) print(s.replace(" ","")) 结果: 5 5 id()#获取对 ...