题解 小L的数列
重度卡常题,还不给O2
发现看着很像矩阵优化,所以试着放到矩阵上
发现乘法可以转化为每个底数的幂次的加法,于是可以转移了
具体地,考虑矩阵乘法的实际意义,可以用初始矩阵的一列来描述一个 \(f_i\)
然后转移就很好写了,\(b_{k, j}\) 的实际意义就是一列要乘的系数
复杂度 \(O(k^3logn)\),会被卡成50pts
若是每次转移 \(k\) 轮而不是1轮就可以到 \(O(k^3log\frac{n}{k})\),就可以过了
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, k;
ll b[N], f[N];
const ll mod=998244353;
const ll mod2=mod-1;
const int imod2=mod2;
inline void md2(int& a, int b) {a+=b; a=a>=imod2?a-imod2:a;}
inline ll qpow(ll a, ll b) {ll ans=1ll; for (; b; b>>=1,a=a*a%mod) if (b&1) ans=ans*a%mod; return ans;}
namespace force{
void solve() {
for (int i=k+1; i<=n; ++i) {
f[i]=1;
for (int j=1; j<=k; ++j) {
f[i]=f[i]*qpow(f[i-j], b[j])%mod;
}
}
printf("%lld\n", f[n]);
exit(0);
}
}
namespace task1{
struct matrix{
int a[205][205], n, m;
matrix(){memset(a, 0, sizeof(a));}
matrix(int x, int y){n=x; m=y; memset(a, 0, sizeof(a));}
inline void resize(int x, int y){n=x; m=y; memset(a, 0, sizeof(a));}
void put() {for (int i=1; i<=n; ++i) {for (int j=1; j<=m; ++j) cout<<a[i][j]<<' '; cout<<endl;} cout<<endl;}
inline int* operator [] (int t) {return a[t];}
inline matrix operator * (matrix b) {
matrix ans(n, b.m);
for (int i=1; i<=n; ++i)
for (int k=1; k<=m; ++k) if (a[i][k])
for (int j=1; j<=b.m; ++j)
md2(ans[i][j], 1ll*a[i][k]*b[k][j]%mod2);
return ans;
}
}mat, t;
matrix qpow(matrix a, ll b) {matrix ans=a; --b; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
inline ll qpow(ll a, ll b) {ll ans=1ll; for (; b; b>>=1,a=a*a%mod) if (b&1) ans=ans*a%mod; return ans;}
void solve() {
if (n<=k) {printf("%lld\n", f[n]); exit(0);}
mat.resize(k, k); t.resize(k, k);
for (int i=1; i<=k; ++i) mat[i][i]=1;
for (int i=2; i<=k; ++i) t[i][i-1]=1;
for (int i=1; i<=k; ++i) t[i][k]=b[k-i+1];
#if 0
cout<<"---mat---"<<endl;
mat.put();
cout<<"---t---"<<endl;
t.put();
mat=mat*t;
cout<<"---ans---"<<endl;
mat.put();
#endif
t=qpow(t, n-k);
// cout<<"---t---"<<endl;
// t.put();
mat=mat*t;
ll ans=1;
// cout<<"---ans---"<<endl;
// mat.put();
for (int i=1; i<=k; ++i) ans=ans*qpow(f[i], mat[i][k])%mod;
printf("%lld\n", ans);
exit(0);
}
}
signed main()
{
freopen("seq.in", "r", stdin);
freopen("seq.out", "w", stdout);
n=read(); k=read();
bool all_one=1;
for (int i=1; i<=k; ++i) b[i]=read();
for (int i=1; i<=k; ++i) {
f[i]=read();
if (f[i]!=1) all_one=0;
}
// force::solve();
if (all_one) {puts("1"); return 0;}
else task1::solve();
return 0;
}