总结:
数据范围问题(int / long long )
题意问题
try a try. 1e4dinic冲冲冲
不要看到过的人暂时比较少就不敢写,@byf
比赛不要划水聊天
题解:
A Blank
题意:题目意思是让你去找一个有n个数的数组,这个数组里面的数只有{0,1,2,3}。然后给你m个条件,每个条件有一组l,r,x,表示在数组l,r区间的有x个不同的数。
问你这样的数组有多少个。
思路:比赛时没想到,,,看题解写的。定义 dp[i][j][k][t] 代表填完前 t 个位置后,{0, 1, 2, 3} 这 4 个数字最后一次出现的位置,排序后为 i, j, k, t(i < j < k < t) 的方案数目,则按照第 t + 1 位的数字的四种选择,可以得到四种转移。对于限制可以按照限制区间的右端点分类,求出 dp[i][j][k][t] 后,找到所有以 t 为区间右端点的限制条件,如果当前状态不满足所有限制条件则不合法,不再向后转移。
参考代码:
#include<bits/stdc++.h> using namespace std; #define pii pair<in,int> #define mkp make_pair #define fi first #define se second #define pb push_back #define mod 998244353 typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } void add(int &a,int b){a+=b;if(a>=mod)a-=mod;} const int maxn=110; int T,n,m,ans; int f[maxn][maxn][maxn][2]; vector<pair<int,int> > d[maxn]; int main() { T=read(); while(T--) { int l,r,x; ans=0; n=read();m=read(); for(int i=1;i<=n;i++) { d[i].clear(); d[i].pb(mkp(i,1)); } for(int i=1;i<=m;i++) { l=read(),r=read(),x=read(); d[r].pb(mkp(l,x)); } memset(f,0,sizeof(f)); f[0][0][0][0]=1; for(int cur=1;cur<=n;++cur) { int o=cur&1; for(int i=0;i<=cur;++i) for(int j=i;j<=cur;++j) for(int k=j;k<=cur;++k) f[i][j][k][o]=0; for(int i=0;i<=cur;++i) for(int j=i;j<=cur;++j) for(int k=j;k<=cur;++k) { add(f[j][k][cur-1][o],f[i][j][k][o^1]); add(f[i][k][cur-1][o],f[i][j][k][o^1]); add(f[i][j][cur-1][o],f[i][j][k][o^1]); add(f[i][j][k][o],f[i][j][k][o^1]); } for(int i=0;i<=cur;++i) for(int j=i;j<=cur;++j) for(int k=j;k<=cur;++k) { for(auto pi:d[cur]) { int l=pi.first,r=cur,x=pi.second; if((i>=l)+(j>=l)+(k>=l)+(cur>=l)!=x) f[i][j][k][o]=0; } } } for(int i=0;i<=n;++i) for(int j=i;j<=n;++j) for(int k=j;k<=n;++k) add(ans,f[i][j][k][n&1]); printf("%d\n",ans); } return 0; }