专栏文章
题解:qoj 9479
题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min6dotq
- 此快照首次捕获于
- 2025/12/01 21:18 3 个月前
- 此快照最后确认于
- 2025/12/01 21:18 3 个月前
因为限制长成了环形的鬼样子,导致一个一个数地填维护限制非常困难,必须将填的过程对每个数同时进行。但是注意到 的样子很二进制,可以发现该式上 最低位只有限地影响得数最低几位。因此有逐位确定的想法,可以在当前最低位上,对每个数的该位进行填,以凑出 的这一位。那么就得到了分讨 最低位 + 递归的做法。其中每三位凑出 的情况,相当于填 环列,不能有连续的三个 和连续的两个 。可以递推,矩阵乘法加速。
CPP#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
struct Matrix {
int a[3][3];
}I, ori, trans;
Matrix operator *(const Matrix &a,const Matrix &b){
Matrix ret;
for(int i=0;i<=2;i++) for(int j=0;j<=2;j++){
ret.a[i][j] = 0;
for(int k=0;k<=2;k++) ret.a[i][j] = (ret.a[i][j] + 1ll * a.a[i][k] * b.a[k][j] % mod) % mod;
}
return ret;
}
Matrix ksm(Matrix s,int cnt){
Matrix ret = I;
while(cnt){
if(cnt & 1) ret = ret * s;
s = s * s;
cnt >>= 1;
}
return ret;
}
int N, M, S;
map<int,int> f;
int dfs(int M){
if(f.find(M) != f.end()) return f[M];
if(M == 0) return 1;
if(M == 1) return S;
int s;
if(M & 1) s = 1ll * dfs((M-1)/2) * S % mod;
else s = (1ll * dfs(M/2) + dfs(M/2-1)) % mod;
f[M] = s;
return s;
}
int main(){
I.a[0][0] = 1, I.a[1][1] = 1, I.a[2][2] = 1;
trans.a[1][0] = 1, trans.a[2][1] = 1, trans.a[0][2] = 1, trans.a[1][2] = 1;
ori.a[0][2] = 1;
scanf("%d%d",&N,&M);
ori = ori * ksm(trans, N-3);
S = ori.a[0][2];
ori = ori * trans;
S = (1ll * S + ori.a[0][2] + ori.a[0][1]) % mod;
ori = ori * trans;
S = (1ll * S + ori.a[0][1] + ori.a[0][0]) % mod;
printf("%d\n",dfs(M));
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...