#矩阵乘法#洛谷 5343 【XR-1】分块
分析
考虑dp,\(dp[i]=\sum dp[i-j]\)
既然\(j\)很小,那么这显然可以用矩阵乘法优化
代码
#include <cstdio>
#include <cctype>
#include <bitset>
#include <cstring>
#define rr register
using namespace std;
const int N=101,mod=1000000007;
bitset<N>cnt1,cnt2; long long n;
struct maix{int p[N][N];}ANS,A;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void Mo(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
inline maix mul(maix A,maix B){
rr maix C;
memset(C.p,0,sizeof(C.p));
for (rr int i=1;i<N;++i)
for (rr int j=1;j<N;++j)
for (rr int k=1;k<N;++k)
Mo(C.p[i][j],1ll*A.p[i][k]*B.p[k][j]%mod);
return C;
}
signed main(){
scanf("%lld",&n),ANS.p[1][0]=1;
for (rr int T=iut();T;--T) cnt1[iut()]=1;
for (rr int T=iut();T;--T) cnt2[iut()]=1; cnt1&=cnt2;
for (rr int i=1;i<N;++i)
if (cnt1[i]) A.p[N-i][N-1]=1;
for (rr int i=2;i<N;++i) A.p[i][i-1]=1;
for (rr int i=1;i<N;++i)
for (rr int j=0;j<i;++j) if (cnt1[i-j])
Mo(ANS.p[1][i],ANS.p[1][j]);
if (n<N) return !printf("%d",ANS.p[1][n]);
for (n-=N-1;n;n>>=1,A=mul(A,A))
if (n&1) ANS=mul(ANS,A);
return !printf("%d",ANS.p[1][N-1]);
}