首页 > 其他 > 详细

DAY 5

时间:2020-11-03 23:30:12      阅读:60      评论:0      收藏:0      [点我收藏+]

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
  • 代码
  • 技术分享图片
    #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;
    } 
    View Code

     

T2 :

  • 树上问题的状态转移分析在于最后一步的有效信息提供
  • 由下而上分配:增加子节点答案x2,父亲节点答案+1//和这个儿子节点构成新的
  • 由此可得
  • 技术分享图片
    #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;
    }
    View Code

     

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;
const int mod=1e9+7;
int f[41][maxn+300],g[11][maxn+300];
int x,y,z,n;

int main()
{
    freopen("poem.in","r",stdin);
    freopen("poem.out","w",stdout);
    scanf("%d%d%d%d",&n,&x,&y,&z);
    y+=x;z+=y;
    int maxs=1<<z;    //printf("%d %d \n",y,maxs);
    for(int i=1;i<=10;i++) g[i][maxs]=maxs;
    for(int s=1;s<maxs;s++)//dp数组按照dp顺序来定义会舒服一点 
        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<<(i+k);
            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;
} 
View Code

这一题我只能说,状态设计的简直是艺术

 

DAY 5

原文:https://www.cnblogs.com/ILHYJ/p/13922277.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!