vijos 1067 Warcraft III 守望者的烦恼 矩阵

时间:2023-12-06 10:00:44

题目链接

我们可以很容易的推出dp的式子, dp[i] = sigma(j : 1 to k) dp[i-j]。

但是n太大了, 没有办法直接算, 所以我们构造一个矩阵, 然后快速幂就好了。

vijos 1067 Warcraft III 守望者的烦恼    矩阵

就像这样构建矩阵(举个例子

#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = ;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
ll n, m, dp[];
struct Matrix
{
ll a[][];
Matrix() {
mem(a);
}
};
Matrix operator * (Matrix a, Matrix b) {
Matrix c;
for(int i = ; i<n; i++) {
for(int j = ; j<n; j++) {
for(int k = ; k<n; k++) {
c.a[i][j] += a.a[i][k]*b.a[k][j];
c.a[i][j] %= mod;
}
}
}
return c;
}
Matrix operator ^(Matrix a, ll b) {
Matrix tmp;
for(int i = ; i<n; i++)
tmp.a[i][i] = ;
while(b) {
if(b&)
tmp = tmp*a;
a = a*a;
b>>=;
}
return tmp;
}
int main()
{
ll k;
cin>>n>>k;
dp[] = ;
for(int i = ; i<=n; i++) {
for(int j = ; j<i; j++)
dp[i] += dp[j];
}
if(k<=n) {
cout<<dp[k]<<endl;
return ;
}
Matrix tmp, ans;
for(int i = ; i<n; i++) {
tmp.a[][i] = ;
tmp.a[i+][i] = ;
}
tmp = tmp^(k-n);
for(int i = ; i<n; i++) {
ans.a[n-i-][] = dp[i+];
}
ans = tmp*ans;
cout<<ans.a[][]<<endl;
return ;
}