2019.05.25 模擬 A 組 T2 數格子

題目:


解題思路:

60pts60pts

暴搜搜出前面幾個的答案

然後枚舉每一項的係數再枚舉一個常數項推出規律

規律: fn = fn1 + 5×fn2 + fn3  fn4\ f_n\ =\ f_{n-1}\ +\ 5\times f_{n-2}\ +\ f_{n-3}\ -\ f_{n-4}

然後將搜索出來的前四項帶入

100pts100pts

矩陣乘法優化

Accepted code:Accepted\ code:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

typedef long long ll;

int n, m, Ans;
ll a[10][10], t[10][10], ans[10][10];

bool read(int &x, int &y) {
	x = y = 0; char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) y = y * 10 + c - 48, c = getchar();
	return x + y;
}

void Matrix(int flag) {
    memset(ans, 0, sizeof(ans));
    for (int i = 1; i <= 4; i++) {
        for (int j = 1; j <= 4; ++j) {
            for (int k = 1; k <= 4; ++k) {
                ans[i][j] += (t[i][k]*(flag==1?a[k][j]:t[k][j]) + m) % m;
                ans[i][j] %= m;
            }
        }
    }
    for (int i = 1; i <= 4; ++i)
    	for (int j = 1; j <= 4; ++j)
    		if (flag) a[i][j] = ans[i][j];
    		else t[i][j] = ans[i][j];
}

ll fuck(ll n) {
    t[1][1] = 1, t[1][2] = 5, t[1][3] = 1, t[1][4] = -1;
	t[2][1] = 1, t[2][2] = 0, t[2][3] = 0; t[2][4] = 0;
    t[3][1] = 0; t[3][2] = 1; t[3][3] = 0; t[3][4] = 0;
    t[4][1] = 0; t[4][2] = 0; t[4][3] = 1; t[4][4] = 0;   
    while(n) {
        if (n & 1) Matrix(1);
        Matrix(0);
        n >>= 1;
    }
    return a[1][1];
}

int main() {
    while(read(n, m)) {
        if(n == 1) Ans = 1;
        else if(n == 2) Ans = 5;
        else if(n == 3) Ans = 11;
        else if(n == 4) Ans = 36;
        else {
            memset(a, 0, sizeof(a));
            a[1][1] = 36;
            a[2][1] = 11;
            a[3][1] = 5;
            a[4][1] = 1;
            Ans = fuck(n - 4);
        }
    	printf("%d\n", Ans % m);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章