zoukankan      html  css  js  c++  java
  • HDU 6198 2017沈阳网络赛 线形递推

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6198

    题意:给出一个数k,问用k个斐波那契数相加,得不到的数最小是几。

    解法:先暴力打表看看有没有规律。

    #include <bits/stdc++.h>
    using namespace std;
    int dp[2000][2000];
    typedef long long LL;
    int main()
    {
        LL c[50];
        c[0]=0;
        c[1]=1;
        c[2]=1;
        for(int i=2; i<50; i++) c[i] = c[i-1]+c[i-2];
        dp[0][0]=1;
        for(int i=0; i<=40; i++){
            for(int j=1; j<=40; j++){
                for(int k=c[i]; k<=1000; k++){
                    dp[j][k] = dp[j][k] + dp[j-1][k-c[i]];
                }
            }
        }
        for(int i=1; i<=40; i++)
            for(int j=1; j<=1000; j++)
        if(dp[i][j]==0){
            printf("%d
    ", j);
            break;
        }
    }
    

     然后发现这恰好是一个线形递推,递推式就是dp[n]=dp[n-1]*3-dp[n-2]+1。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int mod = 998244353;
    struct Matrix{
        LL a[3][3];
        void set1(){
            memset(a, 0, sizeof(a));
        }
        void set2(){
            set1();
            for(int i=0; i<3; i++) a[i][i]=1;
        }
        void set3(){
            a[0][0]=3,a[0][1]=-1,a[0][2]=1;
            a[1][0]=1,a[1][1]=0,a[1][2]=0;
            a[2][0]=0,a[2][1]=0,a[2][2]=1;
        }
        void set4(){
            set1();
            a[0][0]=12;
            a[1][0]=4;
            a[2][0]=1;
        }
    };
    Matrix operator*(const Matrix &a, const Matrix &b){
        Matrix res;
        res.set1();
        for(int i=0; i<3; i++){
            for(int j=0; j<3; j++){
                for(int k=0; k<3; k++){
                    res.a[i][j] = (res.a[i][j]+a.a[i][k]*b.a[k][j]+mod)%mod;
                }
            }
        }
        return res;
    }
    Matrix qsm(Matrix a, int n){
        Matrix res;
        res.set2();
        while(n){
            if(n&1) res=res*a;
            a=a*a;
            n/=2;
        }
        return res;
    }
    int main()
    {
        int n;
        while(scanf("%d", &n)!=EOF)
        {
            if(n==1) printf("4
    ");
            else if(n==2) puts("12");
            else{
                Matrix a,b;
                a.set3();
                b.set4();
                a = qsm(a,n-2);
                a=a*b;
                printf("%lld
    ", (a.a[0][0]+mod)%mod);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    动态规划-树形dp
    排队打水
    耍杂技的牛
    合并果子
    贪心问题-区间类
    动态规划-状态压缩dp
    Linux分区知识及企业场景分区76
    企业面试题-find结合sed查找替换
    企业面试题-利用三剑客
    alias-unalias
  • 原文地址:https://www.cnblogs.com/spfa/p/7506558.html
Copyright © 2011-2022 走看看