zoukankan      html  css  js  c++  java
  • BZOJ_3231_[Sdoi2008]递归数列_矩阵乘法

    BZOJ_3231_[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
    第四行包含三个自然数m, n, p

    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


    用c矩阵做矩阵乘法。

    由于需要求和我们在矩阵中加一项表示Sn。

    然后直接上矩阵快速幂。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define N 20
    ll p,c[N],a[N],b[N],s[N];
    int n,m;
    struct Mat {
    	ll v[N][N];
    	Mat() {memset(v,0,sizeof(v));}
    	Mat operator * (const Mat &x) const {
    		Mat re; int i,j,k;
    		for(i=1;i<=m;i++) {
    			for(j=1;j<=m;j++) {
    				for(k=1;k<=m;k++) {
    					re.v[i][j]=(re.v[i][j]+v[i][k]*x.v[k][j])%p;
    				}
    			}
    		}
    		return re;
    	}
    }X;
    Mat qp(Mat x,ll y) {
    	Mat I;
    	int i;
    	for(i=1;i<=m;i++) I.v[i][i]=1;
    	for(;y;y>>=1ll,x=x*x) if(y&1ll) I=I*x;
    	return I;
    }
    ll getS(ll y) {
    	if(y<=n) return s[y];
    	Mat T=qp(X,y-n);
    	ll re=0;
    	int i;
    	for(i=1;i<=n;i++) re=(re+a[i]*T.v[m][i])%p;
    	re=(re+s[n]*T.v[m][m])%p;
    	return re;
    }
    int main() {
    	scanf("%d",&n);
    	int i;
    	ll l,r;
    	for(i=1;i<=n;i++) scanf("%lld",&b[i]);
    	for(i=1;i<=n;i++) scanf("%lld",&c[i]);
    	scanf("%lld%lld%lld",&l,&r,&p);
    	for(i=1;i<=n;i++) a[n-i+1]=b[i];
    	for(i=1;i<=n;i++) s[i]=s[i-1]+a[i];
    	for(i=1;i<=n;i++) X.v[1][i]=X.v[n+1][i]=c[i];
    	for(i=2;i<=n;i++) X.v[i][i-1]=1;
    	m=n+1;
    	X.v[m][m]=1;
    	// printf("%lld %lld
    ",l,r);
    	// printf("%lld
    ",getS(l-1));
    	printf("%lld
    ",(getS(r)-getS(l-1)+p)%p);
    }
    
  • 相关阅读:
    606. Construct String from Binary Tree
    696. Count Binary Substrings
    POJ 3255 Roadblocks (次短路)
    POJ 2823 Sliding Window (单调队列)
    POJ 1704 Georgia and Bob (博弈)
    UVa 1663 Purifying Machine (二分匹配)
    UVa 10801 Lift Hopping (Dijkstra)
    POJ 3281 Dining (网络流之最大流)
    UVa 11100 The Trip, 2007 (题意+贪心)
    UVaLive 4254 Processor (二分+优先队列)
  • 原文地址:https://www.cnblogs.com/suika/p/9279122.html
Copyright © 2011-2022 走看看