$DP$选讲

直接上题吧

放个题单

[各省省选DP](https://www.luogu.com.cn/training/151079)

$P5322[BJOI2019]$排兵布阵

一眼题,考虑$dp[i][j]$表示已经确定前$i$个的选的数量$j$的最大收益,考虑怎么转移

直接转移这一维和上一维的数量,枚举复杂度$O(n\times m^2)$

那么显然的是直接枚举有很多状态无用,那么有用的决策点只有$k$个

那么直接枚举决策点,那么非决策点必定不优,显然的是就是你在两个决策点之间

花费是无用的,那么复杂度变为$O(n\times m\times k)$

  1. #include<bits/stdc++.h>
  2. #define MAXM 20005
  3. #define MAXN 150
  4. using namespace std;
  5. inline int rd(){
  6. int x=0,f=1;char ch=getchar();
  7. while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
  8. while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
  9. return x*f;
  10. }
  11. int jc[MAXN][MAXN];
  12. int a,s,n,m,val[MAXN][MAXN],dp[2][MAXM];
  13. int main()
  14. {
  15. cin>>s>>n>>m;
  16. for(int i=1;i<=s;i++)
  17. {
  18. for(int j=1;j<=n;j++)
  19. {
  20. a=rd();
  21. jc[j][i]=a;
  22. }
  23. }
  24. for(int i=1;i<=n;i++)
  25. {
  26. sort(jc[i]+1,jc[i]+1+s);
  27. for(int j=1;j<=s;j++)
  28. {
  29. val[i][j]=2*jc[i][j]+1;
  30. }
  31. }
  32. for(int i=1;i<=n;i++)
  33. {
  34. int now=(i&1),pre=(now^1);
  35. // memset(dp[now],0xcf,sizeof(dp[now]));
  36. for(int k=0;k<=s;k++)
  37. {
  38. for(int j=0;j<=m;j++)
  39. {
  40. if(j<val[i][k])
  41. {
  42. dp[now][j]=max(dp[now][j],dp[pre][j]);
  43. }
  44. else
  45. {
  46. dp[now][j]=max(dp[now][j],max(dp[pre][j],dp[pre][j-val[i][k]]+i*k));
  47. }
  48. }
  49. }
  50. // for(int j=0;j<=m;j++)
  51. // {
  52. // cout<<dp[now][j]<<" ";
  53. // }
  54. // cout<<endl;
  55. }
  56. cout<<dp[n&1][m]<<endl;
  57. }
  58. /*
  59. 1 3 10
  60. 2 2 6
  61.  
  62. ./a.exe<a.in>a.out
  63.  
  64. 2 3 10
  65. 2 2 6
  66. 0 0 0
  67. */

$BJOI[2019]$奥术神杖

上来第一眼没有思路,由于直接$DP$显然不好求解,而且这个记录贡献的方式很生草

先考虑如果确定了最后状态,那么答案怎么求$?$

$\sqrt{\Pi_{i=1}^{|s|}v[i]}^{|s|}$

就是把所有出现的咒语乘起来,对总次数开根号

套路,取$log$

那么式子变为

$Ans=log(\sqrt{\Pi_{i=1}^{|s|}v[i]}^{|s|})$

$Ans=log((\Pi_{i=1}^{|s|}v[i])^\frac{1}{|s|})$

$Ans=\frac{1}{|s|}log(\Pi_{i=1}^{|s|}v[i])$

$Ans=\frac{1}{|s|}\sum_{i=1}^{|s|}log(v[i])$

(不得不说$log$乘法转加法真的很好用)

再次发现,这个东西无法直接转移

以我的理解是这个不满足最优子问题结构,无法设计一个好的状态去转移,就是说你用这个状态无法能去转移

就是无法设计一个状态去转移,就是即使你设计$dp[i][j]$也无法完整考虑个数这个问题

而且你次数与次数之间没办法转移,即使你当前保证是当前乘积最大值,也不能开完之后还是最大值

或许你可以换个状态,$dp[i][j]$表示确定了$i$位,匹配$j$个的乘积最大值

发现没办法转移,你需要确定这一位,然后并不知道匹配了多少个

你又说,再多设一维,并且把$dp$设在$AC$自动机上

$dp[i][j][k]$表示目前确定了$i$位,已经匹配了$j$个,目前在$AC$自动机的第$k$个节点的最大乘积

大概的转移方式就是$dp[i+1][j+val[y]][y]=dp[i][j][k]$

结果发现这个可以转移。。。但是你看看这个复杂度就很不友好

在极限数据下的话$dp$状态数是$O(n\times n^2\times cnt)$

分别是$n$个位置,一共所有可能匹配数目$n^2$,和$AC$自动机的节点数

那么用一个很好的套路,对于这种样子带着小数的$dp$,显然可以想到分数规划

然后判断是否合法吧

那么就是这个样子$\frac{1}{|s|}\sum_{i=1}^{|s|}log(v[i])>=mid$

$\sum_{i=1}^{|s|}(log(v[i])-mid)>=0$

那么对于每个贡献$-=mid$,然后转移这个式子的最大值,判断是否大于$0$

发现一个很有意思的事情,这个式子不存在那个烦人的开根号,只需要累和就好了

然后这个也不必关心匹配了几个,只需要一直累加就好了,貌似就解决了

大概重新透彻了分数规划的意义,就是某些状态转移需要和数量或其他有关联

那么就分数规划化简式子,换一种统计方法得到最优

也就是这道题,直接转移不好写,化简完式子之后发现只需要发现有了一个新的匹配直接加上新的匹配的贡献就好了

这个也很好的解决了,式子本身含义也是所有出现的贡献累加起来

这个式子的最大值很好转移

设$dp[i][j]$表示目前已经确定了$i$位,转移到了第$j$个节点的这个式子的最大值

那么转移的话也很简单了

而且这样转移和$AC$自动机匹配性质一样,显然可以得到所有的状态,而且贡献正确

  1. #include<bits/stdc++.h>
  2. #define INF 2147473647
  3. #define MAXN 2005
  4. using namespace std;
  5. const double eps=1e-5;
  6. int tr[MAXN][15],End[MAXN],fail[MAXN],cnt,n;
  7. int zy[MAXN][MAXN][2];
  8. double F[MAXN][MAXN],val[MAXN];
  9. char T[MAXN];
  10. void Insert(char *s,double w)
  11. {
  12. int now=0;
  13. for(int i=1;s[i];i++)
  14. {
  15. if(!tr[now][s[i]-'0'])
  16. {
  17. tr[now][s[i]-'0']=++cnt;
  18. }
  19. now=tr[now][s[i]-'0'];
  20. }
  21. End[now]++;
  22. val[now]+=w;
  23. }
  24. void Get_fail()
  25. {
  26. queue<int>q;
  27. int now=0;
  28. for(int i=0;i<10;i++)
  29. {
  30. if(tr[now][i])
  31. {
  32. q.push(tr[now][i]);
  33. }
  34. }
  35. while(!q.empty())
  36. {
  37. int now=q.front();
  38. End[now]+=End[fail[now]];
  39. val[now]+=val[fail[now]];
  40. q.pop();
  41. for(int i=0;i<10;i++)
  42. {
  43. if(tr[now][i])
  44. {
  45. fail[tr[now][i]]=tr[fail[now]][i];
  46. q.push(tr[now][i]);
  47. }
  48. else
  49. {
  50. tr[now][i]=tr[fail[now]][i];
  51. }
  52. }
  53. }
  54. }
  55. char Ans[MAXN];
  56. double dp(double v)
  57. {
  58. for(int i=0;i<=cnt;i++)
  59. {
  60. val[i]-=End[i]*v;
  61. }
  62. for(int i=0;i<=n;i++)
  63. {
  64. for(int j=0;j<=cnt;j++)
  65. {
  66. F[i][j]=-1e100;
  67. }
  68. }
  69. F[0][0]=0;
  70. for(int i=0;i<n;i++)
  71. {
  72. for(int j=0;j<=cnt;j++)
  73. {
  74. if(F[i][j]>-1e99)
  75. {
  76. for(int k=0;k<10;k++)
  77. {
  78. if(T[i]!='.'&&T[i]!=k+'0') continue;
  79. int y=tr[j][k];
  80. if(F[i+1][y]<F[i][j]+val[y])
  81. {
  82. F[i+1][y]=F[i][j]+val[y];
  83. zy[i+1][y][0]=j;
  84. zy[i+1][y][1]=k;
  85. //¼Ç¼תÒƵã
  86. }
  87. }
  88. }
  89. }
  90. }
  91. for(int i=0;i<=cnt;i++)
  92. {
  93. val[i]+=End[i]*v;
  94. }
  95. int pos=0;
  96. for(int i=1;i<=cnt;i++)
  97. {
  98. if(F[n][i]>F[n][pos]) pos=i;
  99. }
  100. for(int i=n,now=pos;i;i--)
  101. {
  102. Ans[i]=zy[i][now][1]+'0';
  103. now=zy[i][now][0];
  104. }
  105. return F[n][pos];
  106. }
  107. int m,v;
  108. char s[MAXN];
  109. int main()
  110. {
  111. cin>>n>>m;
  112. scanf("%s",T);
  113. for(int i=1;i<=m;i++)
  114. {
  115. scanf("%s",s+1);
  116. scanf("%d",&v);
  117. Insert(s,log(v));
  118. }
  119. Get_fail();
  120. double l=0,r=log(INF),res=0;
  121. while(r-l>eps)
  122. {
  123. double mid=(l+r)/2.0;
  124. if(dp(mid)>0) res=mid,l=mid;
  125. else r=mid;
  126. }
  127. dp(res);
  128. printf("%s",Ans+1);
  129. }

$ZJOI2019$线段树

也不知道$ZJ$出题人怎么想的,一天三道题都是$DP$

这个还是比较简单了

一个很显然的套路,就是可以考虑换一种枚举方式统计贡献

这个不是每个线段树有多少节点被打标记吗

转化思路为这个节点被多少个线段树打标记去累和

那么$dp[i][j]$表示第$i$个节点在前$j$次复制后有多少个被打标记

那么转移就很显然了

  1. //真是不知道能在线段树上跑DP的出题人怎么想
  2. //首先,这个东西肯定不能每次都重开线段树
  3. //那么在一棵线段树上转移
  4. //dp[now][i]当前节点在前i次操作覆盖了几次
  5. //那么这么显然可以直接转移吧
  6. //我们相当于知道了前面所有线段树的这个点状态
  7. //那么由于转移是独立的,那么该咋搞咋搞
  8. //我在想这个东西貌似不太对,就是说会不会出现
  9. //貌似没有影响,因为不会出现标记为2
  10. //我貌似又忘记一个东西叫,贡献独立
  11. //既然整体不好搞,那我们很显然可以单独计算每一个贡献累加
  12. #include<bits/stdc++.h>
  13. #define int long long
  14. #define mod 998244353
  15. #define MAXN 200005
  16. #define ls (now<<1)
  17. #define rs ((now<<1)|1)
  18. using namespace std;
  19. struct node
  20. {
  21. int l,r,sum;
  22. }tr[MAXN<<2];
  23. int f[MAXN<<2],g[MAXN<<2],tf[MAXN<<2],tg[MAXN<<2],cnt;
  24. void build(int now,int l,int r)
  25. {
  26. tr[now].l=l,tr[now].r=r;
  27. f[now]=0;
  28. g[now]=1;
  29. tf[now]=1;
  30. tg[now]=1;
  31. if(l==r) return ;
  32. int mid=(l+r)>>1;
  33. build(ls,l,mid);
  34. build(rs,mid+1,r);
  35. }
  36. void pdTf(int now,int x)
  37. {
  38. (tr[now].sum*=x)%=mod;
  39. (tf[now]*=x)%=mod;
  40. (f[now]*=x)%=mod;
  41. }
  42. void pdTg(int now,int x)
  43. {
  44. (tg[now]*=x)%=mod;
  45. (g[now]*=x)%=mod;
  46. }
  47. void pd(int now)
  48. {
  49. if(tf[now]!=1)
  50. {
  51. pdTf(ls,tf[now]);
  52. pdTf(rs,tf[now]);
  53. tf[now]=1;
  54. }
  55. if(tg[now]!=1)
  56. {
  57. pdTg(ls,tg[now]);
  58. pdTg(rs,tg[now]);
  59. tg[now]=1;
  60. }
  61. }
  62. void push_up(int now)
  63. {
  64. tr[now].sum=(f[now]+tr[ls].sum+tr[rs].sum)%mod;
  65. }
  66. void change(int now,int l,int r)
  67. {
  68. pd(now);
  69. if(tr[now].l==l&&tr[now].r==r)
  70. {
  71. f[now]=(f[now]+cnt)%mod;
  72. g[now]=g[now]%mod;
  73. pdTf(ls,2);
  74. pdTf(rs,2);
  75. }
  76. else
  77. {
  78. int mid=(tr[now].l+tr[now].r)>>1;
  79. g[now]=(g[now]+cnt)%mod;
  80. if(r<=mid)
  81. {
  82. change(ls,l,r);
  83. pd(rs);
  84. f[rs]=(f[rs]+cnt+mod-g[rs])%mod;
  85. g[rs]=(g[rs]+g[rs])%mod;
  86. pdTf(rs<<1,2);pdTg(rs<<1,2);
  87. pdTf(rs<<1|1,2);pdTg(rs<<1|1,2);
  88. push_up(rs);
  89. }
  90. else if(l>mid)
  91. {
  92. change(rs,l,r);
  93. pd(ls);
  94. f[ls]=(f[ls]+cnt+mod-g[ls])%mod;
  95. g[ls]=(g[ls]+g[ls])%mod;
  96. pdTf(ls<<1,2);pdTg(ls<<1,2);
  97. pdTf(ls<<1|1,2);pdTg(ls<<1|1,2);
  98. push_up(ls);
  99. }
  100. else
  101. {
  102. change(ls,l,mid);
  103. change(rs,mid+1,r);
  104. }
  105. }
  106. push_up(now);
  107. }
  108. int n,m,opt,l,r;
  109. signed main()
  110. {
  111. cin>>n>>m;
  112. build(1,1,n);
  113. cnt=1;
  114. for(int i=1;i<=m;i++)
  115. {
  116. cin>>opt;
  117. if(opt==1)
  118. {
  119. cin>>l>>r;
  120. change(1,l,r);
  121. cnt=(cnt+cnt)%mod;
  122. }
  123. if(opt==2)
  124. {
  125. cout<<tr[1].sum<<endl;
  126. }
  127. }
  128. }

十二省联考2019皮配

简化题意就是每个人有两个性质,每个人有一个体积,还有一些人有性质限制,每种性质有体积限制,最后让求所有的方案数,同一个城市的第一个性质必须相同

那么就可以转化为,每个人是豆子,同一个城市里的是豆荚,同一豆荚里面的颜色相同,最后每种性状有重量限制,问最后的方案数

复杂度O(n\times M\times M)的暴力DP很好给出,设dp[i][j][k]表示已经放了i个物品,黄色的有j重量,圆粒的有k重量的方案数,每次枚举整个豆荚放入哪个颜色,然后乘上放入的圆皱方案数

首先不考虑有限制的豆子

考虑这个东西可以先把豆荚染色,然后由于第二性征和第一性征没有联系,那么就考虑分开转移,然后方案相乘

复杂度O(n\times m)

发现没办法处理有限制的豆子

那么对于无毒的豆荚,可以继续按上面的转移,豆子也是

对于有毒的豆荚,因为有限制,那么需要暴力转移

dp[i][j][k]表示已经在有毒的选了i个,绿色的有j的重量,圆粒的有k的重量的方案数

大概转移dp[i][j][k]=dp[i-1][j-valj][k-valk]+...

然后考虑把背包合并,大概就是枚举无毒的选绿色有多少重量,选圆粒的有多少重量

然后在重量允许的范围内枚举,有毒的选的重量,然后相乘得到总方案

大概就是几个背包的合并

一些细节问题,就是说这个转移颜色的时候,显然是一个豆荚一个豆荚转移,如果这个豆荚有一个有问题,就得全部摘出来

那么还有就是最后怎么合并,大概就是枚举那些有问题的豆荚是怎么选择的颜色,然后现在颜色已经确定了,然后再枚举有问题的豆子选哪个颜色,就好了

还有就是这个DP,第一维和第二维是毫无关系的,而且你这个第一维相对于豆荚转移,而第二维相对于豆子去转移

也就是最后合并的时候,我们两个维度表示的总数可能没关系,第一维表示总数是所有限制豆荚,第二维表示的总数是所有限制豆子

那么就显然了

被卡了好久,我一直没看明白G表示的是什么

这个东西不就是我写的超长的转移吗qaq,我自己没看出来

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. #define mod 998244353
  4. #define MAXN 2505
  5. using namespace std;
  6. int n,c,b[MAXN],s[MAXN],f[MAXN],g[MAXN],pre_f[MAXN],pre_g[MAXN],ht[MAXN];
  7. int city_ht[MAXN],city_sum[MAXN],F[MAXN][MAXN],G[MAXN][MAXN];
  8. void sol()
  9. {
  10. cin>>n>>c;
  11. int C0,C1,D0,D1,All=0;
  12. for(int i=1;i<=c;i++)
  13. {
  14. city_ht[i]=false;
  15. city_sum[i]=0;
  16. }
  17. cin>>C0>>C1>>D0>>D1;
  18. for(int i=1;i<=n;i++)
  19. {
  20. cin>>b[i]>>s[i];
  21. ht[i]=-1;
  22. city_sum[b[i]]+=s[i];
  23. All+=s[i];
  24. }
  25. int K,x;
  26. cin>>K;
  27. for(int i=1;i<=K;i++)
  28. {
  29. cin>>x;
  30. cin>>ht[x];
  31. city_ht[b[x]]=true;
  32. }
  33. memset(f,0,sizeof(f));
  34. pre_f[0]=f[0]=1;
  35. for(int i=1;i<=c;i++)
  36. {
  37. if(city_ht[i]||(!city_sum[i])) continue;
  38. for(int j=C0;j>=city_sum[i];j--)
  39. {
  40. f[j]=(f[j]+f[j-city_sum[i]])%mod;
  41. }
  42. }
  43. for(int i=1;i<=C0;i++) pre_f[i]=(pre_f[i-1]+f[i])%mod;
  44. memset(g,0,sizeof(g));
  45. pre_g[0]=g[0]=1;
  46. for(int i=1;i<=n;i++)
  47. {
  48. if(ht[i]==-1)
  49. {
  50. for(int j=D0;j>=s[i];j--)
  51. {
  52. g[j]=(g[j]+g[j-s[i]])%mod;
  53. }
  54. }
  55. }
  56. for(int i=1;i<=D0;i++) pre_g[i]=(pre_g[i-1]+g[i])%mod;
  57. int Cs=0,Ss=0;
  58. memset(F,0,sizeof(F));F[0][0]=1;
  59. memset(G,0,sizeof(G));
  60. for(int ct=1;ct<=c;ct++)
  61. {
  62. if(city_ht[ct])
  63. {
  64. Cs+=city_sum[ct];
  65. Cs=min(Cs,C0);
  66. for(int i=0;i<=Cs;i++)
  67. {
  68. for(int j=0;j<=Ss;j++)
  69. {
  70. G[i][j]=F[i][j];
  71. }
  72. }
  73. for(int a=1;a<=n;a++)
  74. {
  75. int t=s[a];
  76. if(b[a]==ct&&ht[a]!=-1)
  77. {
  78. Ss+=s[a],Ss=min(Ss,D0);
  79. if(ht[a]==1)
  80. {
  81. for(int i=0;i<=Cs;i++)
  82. {
  83. for(int j=Ss;j>=t;j--)
  84. {
  85. F[i][j]=F[i][j-t];
  86. }
  87. for(int j=t-1;j>=0;j--) F[i][j]=0;
  88. }
  89. }
  90. if(ht[a]>=2)
  91. {
  92. for(int i=0;i<=Cs;i++)
  93. {
  94. for(int j=Ss;j>=t;j--)
  95. {
  96. F[i][j]=(F[i][j]+mod+F[i][j-t])%mod;
  97. }
  98. }
  99. }
  100. if(ht[a]==3)
  101. {
  102. for(int i=0;i<=Cs;i++)
  103. {
  104. for(int j=Ss;j>=t;j--)
  105. {
  106. G[i][j]=G[i][j-t];
  107. }
  108. for(int j=t-1;j>=0;j--) G[i][j]=0;
  109. }
  110. }
  111. if(ht[a]<=1)
  112. {
  113. for(int i=0;i<=Cs;i++)
  114. {
  115. for(int j=Ss;j>=t;j--)
  116. {
  117. G[i][j]=(G[i][j]+mod+G[i][j-t])%mod;
  118. }
  119. }
  120. }
  121. }
  122. }
  123. for(int j=0,t=city_sum[ct];j<=Ss;j++)
  124. {
  125. for(int i=Cs;i>=t;i--) F[i][j]=F[i-t][j];
  126. for(int i=t-1;i>=0;i--) F[i][j]=0;
  127. }
  128. for(int i=0;i<=Cs;i++)
  129. {
  130. for(int j=0;j<=Ss;j++)
  131. {
  132. F[i][j]=(F[i][j]+mod+G[i][j])%mod;
  133. }
  134. }
  135. }
  136. }
  137. int res=0;
  138. for(int i=0;i<=Cs;i++)
  139. {
  140. for(int j=0;j<=Ss;j++)
  141. {
  142. int l1=max(0ll,All-C1-i),r1=C0-i;if(l1>r1) continue;
  143. int l2=max(0ll,All-D1-j),r2=D0-j;if(l2>r2) continue;
  144. int vf=pre_f[r1];
  145. if(l1) vf=(vf+mod-pre_f[l1-1])%mod;
  146. int vg=pre_g[r2];
  147. if(l2) vg=(vg+mod-pre_g[l2-1])%mod;
  148. res=(res+mod+vf*vg%mod*F[i][j]%mod)%mod;
  149. }
  150. }
  151. cout<<res<<endl;
  152. }
  153. int T;
  154. signed main()
  155. {
  156. cin>>T;
  157. while(T--) sol();
  158. }
  159. /*
  160. 1
  161. 10 10
  162. 100 98 100 93
  163. 5 10
  164. 4 5
  165. 1 10
  166. 3 10
  167. 7 10
  168. 7 10
  169. 5 10
  170. 3 10
  171. 4 10
  172. 1 10
  173. 5
  174. 1 1
  175. 3 2
  176. 5 1
  177. 4 0
  178. 2 2
  179.  
  180. */

省选联考$2021$滚榜

会了费用提前就很简单了

  1. //有个东西叫费用提前
  2. //当你枚举这个选了多少个的时候,为了保证后面的也是
  3. //那么后面的就统一加上,然后那么这个时候差不变
  4. //该加多少还是加多少
  5. #include<bits/stdc++.h>
  6. #define int long long
  7. using namespace std;
  8. int dp[1<<13][15][505],a[15],Ans,n,m;
  9. int lowbit(int x)
  10. {
  11. return x&(-x);
  12. }
  13. int Count(int num)
  14. {
  15. int res=0;
  16. while(num)
  17. {
  18. res++;
  19. num-=lowbit(num);
  20. }
  21. return res;
  22. }
  23. signed main()
  24. {
  25. cin>>n>>m;
  26. int Max=0;
  27. a[0]=-1;
  28. for(int i=1;i<=n;i++)
  29. {
  30. cin>>a[i];
  31. if(a[i]>a[Max])
  32. {
  33. Max=i;
  34. }
  35. }
  36. for(int i=1;i<=n;i++)
  37. {
  38. int tar=n*(a[Max]-a[i]+(Max<i));
  39. if(tar<=m)
  40. {
  41. dp[1<<(i-1)][i][tar]=1;
  42. }
  43. }
  44. for(int i=1;i<=(1<<n)-1;i++)
  45. {
  46. int Num=Count(i);
  47. for(int j=1;j<=n;j++)
  48. {
  49. if((i>>(j-1))&1)
  50. {
  51. for(int k=0;k<=m;k++)
  52. {
  53. for(int z=1;z<=n;z++)
  54. {
  55. if(!((i>>(z-1))&1))
  56. {
  57. int tar=k+(n-Num)*max(0ll,a[j]-a[z]+(j<z));
  58. if(tar<=m)
  59. dp[i|(1<<(z-1))][z][tar]+=dp[i][j][k];
  60. }
  61. }
  62. }
  63. }
  64. }
  65. }
  66. for(int i=1;i<=n;i++)
  67. {
  68. for(int j=0;j<=m;j++)
  69. {
  70. Ans+=dp[(1<<n)-1][i][j];
  71. }
  72. }
  73. cout<<Ans<<endl;
  74. }

DP选讲的更多相关文章

  1. PJ可能会用到的动态规划选讲-学习笔记

    PJ可能会用到的动态规划选讲-学习笔记 by Pleiades_Antares 难度和速度全部都是按照普及组来定的咯 数位状压啥就先不讲了 这里主要提到的都是比较简单的DP 一道思维数学巧题(补昨天) ...

  2. PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记

    PJ考试可能会用到的数学思维题选讲 by Pleiades_Antares 是学弟学妹的讲义--然后一部分题目是我弄的一部分来源于洛谷用户@ 普及组的一些数学思维题,所以可能有点菜咯别怪我 OI中的数 ...

  3. 正睿OI DAY3 杂题选讲

    正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...

  4. 2019暑期金华集训 Day6 杂题选讲

    自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...

  5. [转载]CSP-J/S 第一轮知识点选讲

    CSP-J/S 第一轮知识点选讲 转载自这里 感谢原博主的大力整理! 信息学史及基本知识 一.信息学及计算机史 计算机的顶级奖项:图灵奖.冯·诺依曼奖 图灵奖:由ACM(美国计算机协会)设立于1966 ...

  6. [入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样 ...

  7. [胡泽聪 趣题选讲]大包子环绕宝藏-[状压dp]

    Description 你有一个长方形的地图,每一个格子要么是一个障碍物,要么是一个有一定价值的宝藏,要么是一个炸弹,或者是一块空地.你的初始位置已经给出.你每次可以走到上.下.左.右这四个相邻的格子 ...

  8. [提升性选讲] 树形DP进阶:一类非线性的树形DP问题(例题 BZOJ4403 BZOJ3167)

    转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7337179.html 树形DP是一种在树上进行的DP相对比较难的DP题型.由于状态的定义多种多样,因此解法也五 ...

  9. ZROI 暑期高端峰会 A班 Day5 杂题选讲

    CF469E \(n\) 个需要表示的数,请使用最少的 \(2^k\) 或 \(-2^k\) 表示出所有需要表示的数.输出方案. \(n\le 10^5,|a_i|\le 10^5\). 首先每个数肯 ...

随机推荐

  1. 项目:Six Sigma

    六西格玛管理(Six Sigma Management)是20世纪80年代末首先在美国摩托罗拉公司发展起来的一种新型管理方式.推行六西格玛管理就是通过设计和监控过程,将可能的失误减少到最低限度,从而使 ...

  2. arts-week13

    Algorithm 992. Sort Array By Parity II - LeetCode Review https://tls.ulfheim.net/ HTTP协议图解 Tip linux ...

  3. 个人冲刺(四)——体温上报app(二阶段)

    冲刺任务:完成用户注册功能和数据库类 RegisterActivity.java package com.example.helloworld; import android.content.Inte ...

  4. 注意:Spring Boot 2.7开始spring.factories不推荐使用了,接下来这么玩...

    如果你是Spring Boot用户的话,一定有这样的开发体验,当我们要引入某个功能的时候,只需要在maven或gradle的配置中直接引入对应的Starter,马上就可以使用了,而不需要像传统Spri ...

  5. Linux namespace技术应用实践--调用宿主机命令(tcpdump/ip/ps/top)检查docker容器网络、进程状态

    背景 最近偶然听了几堂极客时间的云原生免费公开课程,首次接触到了Linux namespace技术,并了解到这正是现在风头正劲的容器技术基石,引起了自己探究一二的兴趣,结合课程+网络搜索+实践操作,也 ...

  6. Vmware虚拟机安装及相关配置流程

    1.Vmware虚拟软件安装 1.1下载地址 vmware 12 pro 的版本稳定性较好,所有我们最好选择该版本 下载地址:https://www.onlinedown.net/soft/10053 ...

  7. Linux切换中英文输入

    使用xshell登录Linux服务器后,输入的命令正确但是提示命令不存在,这是什么鬼. 通过移动光标可以发现两种字体的宽度不一样 解决方法 shift + 空格 进行切换

  8. 从零开始学Java——个人笔记(持续更新中)

    从零开始学Java 学习流程 第一阶段:建立编程思想 Java概述 变量 运算符 控制结构 数组.排序和查找 面向对象编程(基础) 面向对象编程(中级) 项目&学习以致用 编程之乐 第二阶段: ...

  9. 详解PHP如何实现斐波那契数列的简单实例

    文章来自:有解网 http://www.youjieweb.com/original/index/articleId/64.html 使用场景: 面试 本文讲的是如何用php实现PHP实现斐波那契数列 ...

  10. ffmpeg使用总结

    2021-07-21 初稿 截图 ffmpeg -i <video> -ss <time> -vframes 1 <output_pic> 设置视频封面 ffmpe ...