#矩陣乘法#洛谷 5343 【XR-1】分塊
阿新 • • 發佈:2020-11-03
分析
考慮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]); }