题意:From https://blog.csdn.net/m0_37809890/article/details/102886956
思路:
可以发现转移就是右上角的一个区间前缀和
std只要开1倍空间,个人习惯开2倍滚动数组, 1倍有时候没想清楚的前提下初始化或者求前缀和顺序手抖就会gg,反正时空只有常数倍差距
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef long double ld; 7 typedef pair<int,int> PII; 8 typedef pair<ll,ll> Pll; 9 typedef vector<int> VI; 10 typedef vector<PII> VII; 11 typedef pair<ll,ll>P; 12 #define N 1<<20 13 #define M 1000000 14 #define INF 1e9 15 #define fi first 16 #define se second 17 #define MP make_pair 18 #define pb push_back 19 #define pi acos(-1) 20 #define mem(a,b) memset(a,b,sizeof(a)) 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 23 #define lowbit(x) x&(-x) 24 #define Rand (rand()*(1<<16)+rand()) 25 #define id(x) ((x)<=B?(x):m-n/(x)+1) 26 #define ls p<<1 27 #define rs p<<1|1 28 #define fors(i) for(auto i:e[x]) if(i!=p) 29 30 const int MOD=1e8+7,inv2=(MOD+1)/2; 31 double eps=1e-6; 32 int dx[4]={-1,1,0,0}; 33 int dy[4]={0,0,-1,1}; 34 35 ll s[2][20][20],dp[2][20][20]; 36 int l[N],r[N],m,n; 37 38 int read() 39 { 40 int v=0,f=1; 41 char c=getchar(); 42 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 43 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 44 return v*f; 45 } 46 47 ll readll() 48 { 49 ll v=0,f=1; 50 char c=getchar(); 51 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 52 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 53 return v*f; 54 } 55 56 void add(ll &a,ll b) 57 { 58 a+=b; 59 if(a>=MOD) a-=MOD; 60 if(a<0) a+=MOD; 61 } 62 63 int lcp(int a,int b) 64 { 65 int res=0; 66 per(i,m-1,0) 67 if((a>>i&1)==(b>>i&1)) res++; 68 else break; 69 return res; 70 } 71 72 void solve() 73 { 74 m=read(),n=read(); 75 rep(i,1,n) l[i]=read(),r[i]=read(); 76 rep(v,0,1) 77 rep(j,0,m+1) 78 rep(k,0,m+1) s[v][j][k]=dp[v][j][k]=0; 79 int v=0; 80 dp[v][0][m]=s[v][0][m]=1; 81 rep(i,0,m) 82 per(j,m,0) 83 { 84 add(s[v][i][j],s[v][i][j+1]); 85 if(i) 86 { 87 add(s[v][i][j],s[v][i-1][j]); 88 add(s[v][i][j],-s[v][i-1][j+1]); 89 } 90 } 91 int A,B,C,D; 92 rep(i,1,n) 93 { 94 v^=1; 95 rep(j,0,m) 96 rep(k,0,m) s[v][j][k]=dp[v][j][k]=0; 97 rep(j,l[i],r[i]) 98 { 99 A=lcp(j,l[i]),B=lcp(j,r[i]); 100 if(i<n) C=lcp(j,l[i+1]); 101 else C=0; 102 if(i>1) D=lcp(j,r[i-1]); 103 else D=0; 104 dp[v][C][B]=(dp[v][C][B]+s[v^1][A][D]*j)%MOD; 105 } 106 rep(i,0,m) 107 per(j,m,0) 108 { 109 s[v][i][j]=dp[v][i][j]; 110 add(s[v][i][j],s[v][i][j+1]); 111 if(i) 112 { 113 add(s[v][i][j],s[v][i-1][j]); 114 add(s[v][i][j],-s[v][i-1][j+1]); 115 } 116 } 117 } 118 printf("%I64d ",s[v][m][0]); 119 } 120 121 int main() 122 { 123 //freopen("1.in","r",stdin); 124 //freopen("1.out","w",stdout); 125 int cas=read(); 126 while(cas--) solve(); 127 return 0; 128 }