2019 hdu多校1

悠悠 2023-10-11 09:14 111阅读 0赞

A:一类线性dp,时间卡的有点紧

ContractedBlock.gif ExpandedBlockStart.gif

  1. /*
  2. 定义 dp[t][i][j][k]代表填完前 t 个位置后,{0, 1, 2, 3} 这 4 个数字最后一次出现的位置,
  3. 排序后为 t, i, j, k(t > i > j > k) 的方案数目,则按照第 t 位的数字的四种选择,可以得
  4. 到四种转移。
  5. t选t-1这个位置的数:dp[t][i][j][k]
  6. t选i这个位置的数:dp[t][t-1][j][k]
  7. t选j这个位置的数:dp[t][t-1][i][k]
  8. t选k这个位置的数:dp[t][t-1][i][j]
  9. 枚举r[l]==t+1的所有条件,当且仅当满足所有条件时才进行转移
  10. 最后的方案数=sum{dp[n]}
  11. 总时间复杂度 O(n4)。滚动一维,空间复杂度 O(n3)
  12. */
  13. #include<bits/stdc++.h>
  14. using namespace std;
  15. #define maxn 110
  16. #define ll long long
  17. #define mod 998244353
  18. ll dp[2][maxn][maxn][maxn];
  19. int n,m;
  20. struct Node{
  21. int l,x;
  22. Node(){}
  23. Node(int l,int x):l(l),x(x){}
  24. };
  25. vector<Node>v[maxn];
  26. inline void update(ll &a,ll b){
  27. a=(a+b);
  28. while(a>=mod)a-=mod;
  29. }
  30. int c;
  31. void solve(){
  32. c=0;
  33. dp[c][0][0][0]=1;
  34. for(int t=1;t<=n;t++){
  35. c^=1;
  36. for(int i=0;i<=t;i++)
  37. for(int j=0;j<=i;j++)
  38. for(int k=0;k<=j;k++)
  39. dp[c][i][j][k]=0;
  40. for(int i=0;i<t;i++)
  41. for(int j=0;j<=i;j++)
  42. for(int k=0;k<=j;k++){
  43. update(dp[c][i][j][k],dp[c^1][i][j][k]);
  44. update(dp[c][t-1][j][k],dp[c^1][i][j][k]);
  45. update(dp[c][t-1][i][k],dp[c^1][i][j][k]);
  46. update(dp[c][t-1][i][j],dp[c^1][i][j][k]);
  47. }
  48. for(int p=0;p<v[t].size();p++){
  49. //枚举每个条件
  50. int l=v[t][p].l,x=v[t][p].x;
  51. for(int i=0;i<t;i++)
  52. for(int j=0;j<=i;j++)
  53. for(int k=0;k<=j;k++){
  54. int cnt=1;
  55. if(i>=l)cnt++;
  56. if(j>=l)cnt++;
  57. if(k>=l)cnt++;
  58. if(cnt!=x)dp[c][i][j][k]=0;
  59. }
  60. }
  61. }
  62. }
  63. int main(){
  64. //ios::sync_with_stdio(false);
  65. int t;cin>>t;
  66. while(t--){
  67. for(int i=0;i<maxn;i++)v[i].clear();
  68. scanf("%d%d",&n,&m);
  69. for(int i=1;i<=m;i++){
  70. int l,r,x;
  71. scanf("%d%d%d",&l,&r,&x);
  72. v[r].push_back(Node(l,x));
  73. }
  74. solve();
  75. ll ans=0;
  76. for(int i=0;i<n;i++)
  77. for(int j=0;j<=i;j++)
  78. for(int k=0;k<=j;k++)
  79. ans+=dp[c][i][j][k],ans%=mod;
  80. cout<<ans<<'\n';
  81. }
  82. }

B:线性基前缀和,cf原题

C:待补

D:模拟,二分也可以做

E:队友过得,最短路最小割

F,G,H待补

I:字符串dp,调了半天才做出来

ContractedBlock.gif ExpandedBlockStart.gif

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define maxn 300005
  4. int cnt[maxn][26],nxt[maxn][26],pos[26];
  5. int n,k,l[26],r[26],used[26],up,down;
  6. char ans[maxn],s[maxn];
  7. int judge(int i,int pos){
  8. int res1=0,res2;
  9. for(int j=0;j<26;j++){
  10. if(used[j]+cnt[pos][j] < l[j])return 0;
  11. res1+=max(0,l[j]-used[j]);//后面最少要的字符个数
  12. res2+=min(cnt[pos][j],r[j]-used[j]);//后面最多能的字符个数
  13. }
  14. if(res1>k-i || res2<k-i)return 0;
  15. return 1;
  16. }
  17. void init(){
  18. memset(used,0,sizeof used);
  19. up=down=0;
  20. memset(cnt,0,sizeof cnt);
  21. memset(ans,0,sizeof ans);
  22. }
  23. int main(){
  24. while(scanf("%s%d",s+1,&k)==2){
  25. init();
  26. n=strlen(s+1);
  27. for(int i=0;i<26;i++)scanf("%d%d",&l[i],&r[i]),up+=r[i],down+=l[i];
  28. for(int i=n;i>=1;i--){
  29. for(int j=0;j<26;j++)
  30. if(s[i]-'a'==j)cnt[i][j]=cnt[i+1][j]+1;
  31. else cnt[i][j]=cnt[i+1][j];
  32. }
  33. int flag=0;
  34. if(down>k || up<k){puts("-1");continue;}
  35. for(int i=0;i<26;i++)if(cnt[1][i]<l[i]){puts("-1");flag=1;break;}
  36. if(flag)continue;
  37. for(int i=0;i<26;i++)pos[i]=n+1;
  38. for(int i=n;i>=1;i--){
  39. for(int j=0;j<26;j++)
  40. nxt[i][j]=pos[j];
  41. pos[s[i]-'a']=i;
  42. }
  43. for(int j=0;j<26;j++)nxt[0][j]=pos[j];
  44. int now=0;
  45. for(int i=1;i<=k;i++){
  46. for(int j=0;j<26;j++){
  47. //第i位选择j
  48. if(used[j]>=r[j])continue;
  49. int tmp=nxt[now][j];
  50. used[j]++;
  51. if(judge(i,tmp+1)){
  52. ans[i]=j;
  53. now=tmp;
  54. break;
  55. }
  56. else
  57. used[j]--;
  58. }
  59. }
  60. for(int i=1;i<=k;i++)cout<<(char)(ans[i]+'a');
  61. puts("");
  62. }
  63. }

JKLM:待补

转载于:https://www.cnblogs.com/zsben991126/p/11348002.html

发表评论

表情:
评论列表 (有 0 条评论,111人围观)

还没有评论,来说两句吧...

相关阅读

    相关 2019佳木斯联训 Day1

        T1   非常裸的大模拟,比较简单   思路:用字符串存储数据,然后从后往前查找直到 找到00,25,50,75中的任意一个,然后再用串长相减 判断一下正反关系