#矩阵乘法#洛谷 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]);
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13922363.html