前言
看着与数学有关的题就紧张emmm......
题目
Time Limits: 1500 ms Memory Limits: 524288 KB
Input
一行两个整数n和k。
之后1行k个正整数b1...bk。
之后1行k个正整数f1...fk。
Output
输出一个整数表示fn
Sample Input
样例输入1 5 4 1 2 3 4 4 3 2 1 样例输入2 100000 4 1 2 3 4 12 23 34 45
Sample Output
样例输出1 27648 样例输出2 33508797
【数据范围】
对于30%的数据,n≤10000.
对于另外20%的数据,bi=1,n≤1000000.
对于另外20%的数据,f[1]...f[k-1]=1.
对于另外20%的数据,k≤30.
对于100%的数据,1≤k≤200,1≤n≤40000000,1≤bi,fi≤998244352.
【样例解释】
1*2*2*3*3*3*4*4*4*4=27648
分析
贴个JZOJ的题解...:
sub1,sub2随便做,先考虑subtask3的一种做法,我们只要算那个不是一的数的指数,因此我们可以想到矩阵乘法,因为幂的乘法就相当于指数的加法,乘方相当于乘法。所以我们让向量表示当前为i,i-1---i-k中每个数中fk的指数,初始即为{0,0,0,0,...,0,1},就可以用
for(int i=1;i<=K;++i) a[i][K]=b[i],a[i][i-1]=(i!=1); 这样的矩阵转移。
然后将每个数独立来看,分别做矩乘就可以拿到subtask4的分(复杂度:k^4*logn)。但其实因为矩阵相同,所以可以将矩阵的幂预处理出来(复杂度:k^3*logn),然后就可以AC。
需要注意矩乘时指数是mod p-1(费马小定理)。
注意:n可能小于k,出题人只卡了没有特判的人10分,还送了只写这个的人10分,太良心了!!!!
好吧,好抽象...找找博客
这个博客没看懂(我太弱了):https://blog.youkuaiyun.com/enjoy_pascal/article/details/98750218
再来个博客(俩博客我就不信我看不懂):https://blog.youkuaiyun.com/qq_37656398/article/details/98785796
我醉了,真的看不懂
跑去问LZR,他说:“你想象一下,用脑子想”
这篇暂时咕咕掉... ...
暴力代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1e6,mod=998244353;
ll f[MAXN+5],b[MAXN+5];
ll n,k,ans;
ll Pow(ll a,ll x)//a^x记得取模
{
ll ret=1,tmp=x;
while(x--)
{
ret*=a;
ret%=mod;
}
return ret%mod;
}
int main()
{
//freopen("seq.in","r",stdin);
//freopen("seq.out","w",stdout);
scanf("%lld%lld",&n,&k);
bool flag=true;//fi是否全是1
for(int i=1;i<=k;i++)
scanf("%lld",&b[i]);
for(int i=1;i<=k;i++)
{
scanf("%lld",&f[i]);
if(f[i]!=1)
flag=false;
}
if(flag)
{
printf("1\n");
return 0;
}
else
{
for(int i=k+1;i<=n;i++)
{
f[i]=1;
for(int j=1;j<=k;j++)
f[i]=(f[i]*(Pow(f[i-j],b[j])%mod))%mod;
//printf("%d:%lld\n",i,f[i]%mod);
}
}
printf("%lld",f[n]%mod);
return 0;
}