• BZOJ-3231 递归数列 矩阵连乘+快速幂


    题不是很难,但是啊,人很傻啊。。。机子也很鬼畜啊。。。
    

    3231: [Sdoi2008]递归数列
    Time Limit: 1 Sec Memory Limit: 256 MB
    Submit: 569 Solved: 241
    [Submit][Status][Discuss]

    Description
    一个由自然数组成的数列按下式定义:
    对于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的余数的值。

    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

    Source

    第一次调试:矩阵都是【1001】【1001】虽然很多余,但是理论上并没错,但是机子low每次调用到就炸....
    第二次调试:矩阵的初始化调上次时不小心删了....又WA....
    第三次调试:出现负数,以为爆longlong果断+快速乘,still booming
    然后发现是最后做前缀和减法时..可能减到负了.....
    于是A之,带快速乘版本1600MS+,删之160MS+....珍爱生命远离快速乘TAT
    

    构造的矩阵如下:
    这里写图片描述
    S为前缀和…最后只需要进行前缀和相减即可…

    code:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    long long read()
    {
        long long x=0,f=1; char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    long long k,m,n,p;
    long long s=0;
    long long cc[50],bb[50];
    struct Mat{
        long long da[50][50];
        Mat(){memset(da,0,sizeof(da));}   
    };
    
    //long long quick_mul(long long x,long long y)
    //{
    //    if (y==0) return 0;
    //    if (y==1) return x%p;
    //    long long re;
    //    re=quick_mul(x,y>>1);
    //    if ((y&1)==1) return (re+re+x)%p;
    //             else return (re+re)%p;
    //}
    
    Mat mul(Mat A,Mat B)
    {
        Mat C;
        for (int i=1; i<=k+1; i++)
            for (int j=1; j<=k+1; j++)
                for (int kk=1; kk<=k+1; kk++)
                    C.da[i][j]=(C.da[i][j]+(A.da[i][kk]*B.da[kk][j])%p)%p;
        return C;
    } 
    
    Mat quick_pow(Mat A,long long x)
    {
        Mat re;
        for (int i=1; i<=k+1; i++) re.da[i][i]=1;
        for (long long i=x; i; i>>=1,A=mul(A,A))
            if (i&1) re=mul(re,A);
        return re;
    }
    
    Mat a;
    Mat b;
    void init()
    {
        for (int i=1;i<=k;i++)  a.da[i][1]=a.da[i][k+1]=cc[i];
        for (int i=2;i<=k;i++)  a.da[i-1][i]=1;
        a.da[k+1][k+1]=1;
        for (int i=1;i<=k;i++)  b.da[1][i]=bb[k-i+1];
        b.da[1][k+1]=s;
    }
    
    long long work(long long x)
    {
        if (x==0) return b.da[1][k+1];
        Mat re;
        re=quick_pow(a,x);
        re=mul(b,re);
        return re.da[1][k+1];
    }
    
    int main()
    {
        k=read();
        for (int i=1; i<=k; i++) bb[i]=read();
        for (int i=1; i<=k; i++) cc[i]=read();   
        m=read(),n=read(),p=read();
        for (int i=1; i<=k; i++) bb[i]%=p,s=(s+bb[i])%p,cc[i]%=p;
        long long ans=0;
        if (n<=k) 
            {
                for (int i=m; i<=n; i++) ans=(ans+bb[i])%p;
                printf("%lld
    ",ans);
                return 0;
            }
        init();
        ans=work(n-k);
        if (m>k) ans=(ans-work(m-k-1))%p;
            else for (int i=1; i<m; i++) ans=(ans-bb[i])%p;
        ans=(ans+p)%p;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    python之mysqldb模块安装
    消失的那3个月__怎么看代码的小结
    四年测试经验总结
    python学习笔记系列----(八)python常用的标准库
    业务逻辑中的测试总结(二)----业务与数据库交互需求的测试分解
    python学习笔记系列----(七)类
    【QUESTION】
    python学习笔记系列----(六)错误和异常
    python学习笔记系列----(五)输入和输出
    Android6.0.1 移植:显示系统(一)--测试framebuffer
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346186.html
Copyright © 2020-2023  润新知