DAY 5
T1:
- 预处理的时候没有必要所有的都处理完毕,能够只处理有效信息才是关键/
- 枚举的关键就在于枚举元素和枚举个数的转移
- 例:我需要 li->ri的k次方的前缀和,我可以枚举k,从li->ri加到数组,也可以枚举li->ri,一次加到k的数组当中去
- #请注意:在阶段划分如此明显的前提下,直接想搜索而否定动态规划是不明智的
- 我们考虑到预处理(l1+l2)(r1+r2)...的时候是好事情,这个时候要考虑的是前后的状态转移关系()
- 这里运用到两个重要思想:元素的贡献到底可以怎么贡献?
- 设计状态 表示前i个已经分配j个糖果(考虑j=400dfs绝对爆炸)
- 那么f[i][j]+=f[i-1][j-k]*g[i][k]..相当于枚举i,然后每次单招顺序慢慢补充完一整个方案,也就是对前面的乘上这一次的c
- 代码
-
View Code#include <stdio.h> #include <algorithm> #include <cstring> using namespace std; const int maxn=420; typedef long long ll; const int mod=1e9+7; ll g[maxn][maxn],l[maxn],r[maxn]; int n,c; ll f[maxn][maxn]; int main() { // freopen("candy.in","r",stdin); // freopen("candy.out","w",stdout); scanf("%d%d",&n,&c); for(int i=1;i<=n;i++) scanf("%lld",&l[i]); for(int i=1;i<=n;i++) scanf("%lld",&r[i]); for(int i=1;i<=n;i++) for(int j=l[i];j<=r[i];j++) { ll s=1; for(int k=0;k<=c;k++) (g[i][k]+=s)%=mod,(s*=j)%=mod; } f[0][0]=1;//注意初始状态 for(int i=1;i<=n;i++) for(int j=0;j<=c;j++) for(int k=0;k<=j;k++) (f[i][j]+=(f[i-1][j-k]*g[i][k]+mod)%mod)%=mod;//注意是=还是+= printf("%lld",f[n][c]); return 0; }
T2 :
- 树上问题的状态转移分析在于最后一步的有效信息提供
- 由下而上分配:增加子节点答案x2,父亲节点答案+1//和这个儿子节点构成新的
- 关于题目的分析:
注意一下,分析的时候的顺序就是一般到特殊:
- 也就是分成1节点,字数个数为x和y的两个子节点
- 分析得到连通块的数量是(x+1)(y+1)->由此推导出来公式
- 由此可得
-
View Code#include <stdio.h> #include <algorithm> #include <cstring> #include <iostream> using namespace std; const int maxn=1010; struct node { int u,v; }ans[maxn]; int main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout); int k; while(cin>>k) { int u=1; int len=0; for(int i=1;i<=k;i<<=1) { if(i>1) ans[++len].u=u,ans[len].v=len+1; if((i&k)&&((i<<1)<=k)) ans[++len].u=len+1,ans[len].v=u,u=len+1; } printf("%d\n",len+1); for(int i=1;i<=len;i++) printf("%d %d\n",ans[i].u,ans[i].v); } return 0; }
T3 :
- 关键点:向量的面积计算
- 期望问题本质上就是根据线性期望的性质化简成可以枚举计算的范围以内进行求解
相关知识点,使用行列式和叉乘球多边形的面积:
- 关键点的转化:A,B在凸包上->没有点在AB的右侧+我们需要用叉乘来计算面积->剩下平面上任意一点c在右边<=>和a,b向量之积大于0;
- 由此转化乘1-p[i]也就是不存在的概率
T4
#include <stdio.h> #include <algorithm> #include <cstring> using namespace std; const int maxn=(1<<17)+300; const int mod=1e9+7; int f[41][maxn],g[11][maxn];//状态设计,g表示从1-10增添一个数后由s状态会转移到什么状态 //f[]表示在前i个数位中选择,构成诗的部分状态是s的前提下的方案数 int n,x,y,z; int main() { scanf("%d%d%d%d",&n,&x,&y,&z); y+=x;z+=y; int maxs=1<<z; for(int i=1;i<=10;i++) g[i][maxs]=maxs; for(int s=1;s<maxs;s++) for(int i=1;i<=10;i++) { g[i][s]=1; for(int k=0;k<z;k++) if((s>>k)&1&&i+k<=z&&!(k<x&&k+i>x)&&!(k<y&&k+i>y))g[i][s]|=1<<(k+i); if(g[i][s]>maxs) g[i][s]=maxs; } f[0][1]=1; for(int i=0;i<n;i++) for(int s=1;s<=maxs;s++) { if(f[i][s]) for(int j=1;j<=10;j++)(f[i+1][g[j][s]]+=f[i][s])%=mod; } printf("%d ",f[n][maxs]%mod); return 0; }
这一题我只能说,状态设计的简直是艺术
浙公网安备 33010602011771号