zoukankan      html  css  js  c++  java
  • 8-26模拟赛解题报告

    今天勉强打了打暴力,没有爆零。。(同机房还有一个(170)的dalao┌(。Д。)┐


    T1.chess

    题目大意:一个棋盘上有一些格子有黑棋,有一些格子有白棋

    考场上这题差一点想到正解,可是一时脑抽,就在一条路上走不回来了。。

    直接讲正解吧,这题应该属于插头DP,也叫轮廓线DP,从左上延轮廓线走到右下,向下走为(1),向右走为(0),然后状态就有了,强行(O(n^2))暴力枚举两个点转移,然后判断单个点,就AC了。时间复杂度为(O(C_{2n}^nn^2))

    小结:

    解题关键:想到插头DP的经典状态

    芝士点:插头DP

    duliu出题人,竟然卡常!!!

    手起,码落:

    #include<bits/stdc++.h>
    #define re register
    using namespace std;
    int n,f[(1<<24)+10],len,val[13][13],a[13][13],num[(1<<24)+1],num1[30],mid;
    char ch[13][13];
    void work(int x)
    {
    	num1[0]=(x&1);
    	for(re int j=1;j<(n<<1);j++)
    	{
    		num1[j]=num1[j-1]+((x>>j)&1);
    		if((x>>j&1)==0||(x>>j-1&1))continue;
    		f[x]=min(f[x],f[x^(1<<j)^(1<<j-1)]+val[num1[j]][j-num1[j]+1]);
    		for(re int k=1;k<j;k++)
    		{
    			if((x>>k&1)&&(x>>k-1&1)==0&&a[num1[j]][j-num1[j]+1]+a[num1[k]][k-num1[k]+1]==61)
    				f[x]=min(f[x],f[x^(1<<j)^(1<<j-1)^(1<<k)^(1<<k-1)]+abs(val[num1[j]][j-num1[j]+1]-val[num1[k]][k-num1[k]+1]));
    		}
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	for(re int i=1;i<=n;i++)
    	{
    		scanf("%s",ch[i]+1);
    		for(re int j=1;j<=n;j++)
    			a[i][j]=ch[i][j]-46;
    	}
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=n;j++)
    			scanf("%d",&val[i][j]);
    	memset(f,63,sizeof(f)),len=((1<<(n<<1))-1)^((1<<n)-1),f[(1<<n)-1]=0;
    	for(re int i=1;i<=len;i++)
    	{
    		num[i]=num[i>>1]+(i&1);
    		if(num[i]==n)work(i);
    	}
    	return printf("%d",f[len]),0;
    }
    

    T2.tree

    题目大意:给定(n)个点,第(i)个点的限制为度数不能超过(a_i)。现在对于每一个(1le sle n),问从这(n)个点中选出(s)个点组成有标号无根树的方案数对(10^9+7)取模后的结果。

    一上午死磕T1,第二题看都没看,没想到竟然是一个模板题!(虽然我不会

    前置芝士:Prufer序列

    这题需要一个神奇的东西——Prufer序列,它有一个很好的性质就是和有标号无根树一一对应,主要生成过程如下:

    • 选择一个序号最小的叶子结点,把和这个点相连的点加入序列末端,然后删除这个叶子结点及这条边。

    • 重复以上操作直至剩余两个节点

    而Prufer序列生成无根树的过程也很简单,大家可以自己思考思考 (就是我自己不愿意打了

    进入正题:

    这题求的是有标号无根树的方案树,其实也就是Prufer序列的方案数,直接DP就好了。(f[i][j][k])表示前(i)个节点选择(j)个,在Prefer序列中填了(k)个数的方案数除以((j-2)!)

    然后状态转移方程就出来了:

    [f[i+1][j][k]+=f[i][j][k] ]

    [f[i+1][j+1][k+c]+=frac{f[i][j][k]}{c!} ]

    其中(c)为枚举第(i)个节点的度数限制的值且(0le cle a_{i+1}-1)

    所以最后的答案就是(f[n][s][s-2] imes (s-2)!)

    小结:

    解题关键:这题算模板题吧,想到模板就好了

    芝士点:Prefer序列,有标号无根树计数

    手起,码落:

    #include<bits/stdc++.h>
    #define re register
    #define mod 1000000007
    using namespace std;
    const int N=105;
    inline long long Pow(long long x,int y)
    {
    	re long long sum=1;
    	for(;y;x=(x*x)%mod,y>>=1)
    		if(y&1)sum=(sum*x)%mod;
    	return sum;
    }
    int n,a[N];
    long long f[N][N][N],p[N]={1},inv[N];
    int main()
    {
    	scanf("%d",&n);
    	if(n==0)return printf("0"),0;
    	for(re int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(re int i=1;i<=n;i++)p[i]=p[i-1]*i%mod;
    	inv[n]=Pow(p[n],mod-2);
    	for(re int i=n-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
    	f[0][0][0]=1;
    	for(re int i=0;i<=n;i++)
    		for(re int j=0;j<=i;j++)
    			for(re int k=0;k<=n-2;k++)
    			{
    				if(f[i][j][k]==0)continue;
    				(f[i+1][j][k]+=f[i][j][k])%=mod;
    				for(re int l=0;l<a[i+1]&&k+l<=n-2;l++)
    					(f[i+1][j+1][k+l]+=f[i][j][k]*inv[l]%mod)%=mod;
    			}
    	printf("%d ",n);
    	for(re int i=2;i<=n;i++)printf("%lld ",f[n][i][i-2]*p[i-2]%mod);
    	return 0;
    }
    

    T3.divide

    咕咕咕~~

  • 相关阅读:
    Opengl绘制我们的小屋(二)第一人称漫游
    C# this.Invoke和this.BeginInvoke 最简单的写法
    C# 递归模型定义。赋值
    .net Core 2.1 后 Session保存,新页面获取不到值
    .net core mvc 错误信息显示 ModelState.AddModelError
    .net Core 依赖注入 Add********说明
    C# 中2个问号的作用。C#的??代表是什么意思
    asp.net mvc 加三层架构 完美搭配
    C# DataTable.Compute()用法
    C# DateTime判断时间
  • 原文地址:https://www.cnblogs.com/jkzcr01-QAQ/p/13574150.html
Copyright © 2011-2022 走看看