BZOJ3231: [Sdoi2008]递归数列

Description

一个由自然数组成的数列按下式定义:
对于i <= kai = bi
对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k
其中bj和 cj (1<=j<=k)是给定的自然数。写一个程序,给定自然数m <= n, 计算am + am+1 + am+2 + ... + an, 并输出它除以给定自然数p的余数的值。

Input

由四行组成。
第一行是一个自然数k
第二行包含k个自然数b1, b2,...,bk
第三行包含k个自然数c1, c2,...,ck
第四行包含三个自然数mnp

Output

仅包含一行:一个正整数,表示(am + am+1 + am+2 + ... + an) mod p的值。

Sample Input

2
1 1
1 1
2 10 1000003

Sample Output

142

HINT

对于100%的测试数据:
1<= k<=15
1 <= m <= n <= 1018


题解Here!

矩阵快速幂的沙茶题。
设$Ans(l,r)=\sum_{i=l}^ra_i$。
差一下分:$Ans(l,r)=Ans(1,r)-Ans(1,l-1)$
这种题只要构造出矩阵就万事大吉了。
我们很容易想到把$a_1,a_2,a_3,...,a_k$全部放到矩阵中。
但是求和怎么办?
没事,一并放到矩阵中。
设$sum(x)=\sum_{i=1}^xa_i$。
有这个式子:$$sum(x+1)=sum(x)+a_{x+1}=sum(x)+c_1\times a_{x}+c_2\times a_{x-1}+...+c_k\times a_{x-k+1}$$
所以我们构造出矩阵长这个样:$$\left[\begin{array}{}0&0&0&...&0&c_k&c_k\\1&0&0&...&0&c_{k-1}&c_{k-1}\\0&1&0&...&0&c_{k-2}&c_{k-2}\\0&0&1&...&0&c_{k-3}&c_{k-3}\\&&&......\\0&0&0&...&1&c_1&c_1\\0&0&0&...&0&0&1\end{array}\right]$$
最初的矩阵就是这样:$$\left[\begin{array}{}a_1&a_2&a_3&...&a_k&sum(k)\end{array}\right]$$
而$a_i=b_i,i\in [1,k]$。
然后就可以愉快地跑矩阵快速幂了。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 20
using namespace std;
long long n,m,p,k;
long long b[MAXN],c[MAXN],sum[MAXN];
struct node{
long long val[MAXN][MAXN];
node(){
for(int i=0;i<=19;i++)
for(int j=0;j<=19;j++)
val[i][j]=0;
}
friend node operator *(node x,node y){
node ret;
for(int i=1;i<=k+1;i++)
for(int j=1;j<=k+1;j++){
ret.val[i][j]=0;
for(int l=1;l<=k+1;l++){
ret.val[i][j]+=x.val[i][l]*y.val[l][j]%p;
ret.val[i][j]%=p;
}
}
return ret;
}
friend node operator ^(node x,long long w){
node s;
for(int i=1;i<=k+1;i++)s.val[i][i]=1;
while(w){
if(w&1)s=s*x;
x=x*x;
w>>=1;
}
return s;
}
}a[3];
inline long long read(){
long long date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
long long solve(long long x,int id){
if(x<=k)return sum[x];
node ans;
for(int i=1;i<=k;i++)ans.val[1][i]=b[i];
ans.val[1][k+1]=sum[k];
ans=ans*(a[id]^(x-k));
return ans.val[1][k+1]%p;
}
void work(){
long long ans1=solve(n,1),ans2=solve(m-1,2);
printf("%lld\n",(ans1-ans2+p)%p);
}
void init(){
k=read();
sum[0]=0;
for(int i=1;i<=k;i++){
b[i]=read();
sum[i]=sum[i-1]+b[i];
}
for(int i=1;i<=k;i++)c[i]=read();
m=read();n=read();p=read();
a[1].val[k+1][k+1]=a[2].val[k+1][k+1]=1;
for(int i=1;i<k;i++)a[1].val[i+1][i]=a[2].val[i+1][i]=1;
for(int i=1;i<=k;i++)a[1].val[i][k]=a[1].val[i][k+1]=a[2].val[i][k]=a[2].val[i][k+1]=c[k-i+1];
}
int main(){
init();
work();
return 0;
}

BZOJ3231: [Sdoi2008]递归数列的更多相关文章

  1. [bzoj3231][SDOI2008]递归数列——矩阵乘法

    题目大意: 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj和 cj ...

  2. BZOJ-3231 [SDOI2008]递归数列

    转成矩阵连乘后,矩阵快速幂加速解决. 一开始没把需要longlong的变量补全..而且没初始化2333 #include <cstdlib> #include <cstdio> ...

  3. BZOJ 3231: [Sdoi2008]递归数列( 矩阵快速幂 )

    矩阵乘法裸题..差分一下然后用矩阵乘法+快速幂就可以了. ----------------------------------------------------------------------- ...

  4. BZOJ_3231_[Sdoi2008]递归数列_矩阵乘法

    BZOJ_3231_[Sdoi2008]递归数列_矩阵乘法 Description 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1a ...

  5. 开始玩矩阵了!先来一道入门题![SDOI2008]递归数列

    [SDOI2008]递归数列 题目描述 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + c ...

  6. 【bzoj3231】[Sdoi2008]递归数列 矩阵乘法+快速幂

    题目描述 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj和 cj  ...

  7. P2461 [SDOI2008]递归数列

    题目描述 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai-k 其中bj 和 cj ...

  8. [luogu2461 SDOI2008] 递归数列 (矩阵乘法)

    传送门 Description 一个由自然数组成的数列按下式定义: 对于i <= k:ai = bi 对于i > k: ai = c1ai-1 + c2ai-2 + ... + ckai- ...

  9. [SDOI2008]递归数列

    嘟嘟嘟 裸的矩阵快速幂,构造一个\((k + 1) * (k + 1)\)的矩阵,把sum[n]也放到矩阵里面就行了. #include<cstdio> #include<iostr ...

随机推荐

  1. (2)Unity3d菜单

    1.文件菜单 2.编辑菜单 Frame Selected 焦点选择和双击Hierarchy中的元素一样的功能 Lock View to Selected  选中对象再点击此按钮,在场景视图中移动此对象 ...

  2. chpasswd、dd命令、find实战、添加系统服务、buffer、cached

    1.如果两个文件的每一行想一一对应 paste 1.txt 2.txt # 文件3.txt中存放着用户跟密码,想要添加用户并设置密码: # 用户必须存在,文件格式必须是--用户名:密码 chpassw ...

  3. luogu P3808 【模板】AC自动机(简单版)

    题目背景 这是一道简单的AC自动机模板题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交. 管理员提示:本题数据内有重复的单词,且重复单词应该计算多次, ...

  4. PE 512 Sums of totients of powers

    可以很简单的发现,当n是奇数的时候,f(n)=φ(n),否则f(n)=0. 所以我们就是求n<=5*10^8且n为奇数的φ的和. 首先我们可以做到用杜教筛算出φ的前缀和,但是如何把偶数的减去? ...

  5. OpenGL - Tessellation Shader 【转】

    http://blog.sina.com.cn/s/blog_8c7d49f20102v4qm.html Patch is just an ordered list of vertices (在tes ...

  6. 微服务指南走北(三):Restful API 设计简述

    API的定义取决于选择的IPC通信方式,假设是消息机制(如 AMQP 或者 STOMP).API则由消息频道(channel)和消息类型.假设是使用HTTP机制,则是基于请求/响应(调用http的ur ...

  7. mysql序列号发生器

    mysql序列号发生器 学习了:http://www.jquerycn.cn/a_14577 还可以这样啊:

  8. JAVA Timer定时器使用方法

    JAVA  Timer 定时器测试 MyTask.java:package com.timer; import java.text.SimpleDateFormat;import java.util. ...

  9. 内核顶层Makefile相关1

    http://www.groad.net/bbs/simple/?f104.htm $(Q) 变量 内核 Makefile 文件 238 行到 259 行的注释中知道,$(Q) 变量的作用是决定是否在 ...

  10. B树的生成

    B树的生成 flyfish 2015-7-19 从空树開始构建一棵B树 逐个插入keyword 规则: 除根结点之外的全部非终端结点至少有⌈m/2⌉棵子树,所以keyword的个数必须 n为keywo ...