• 【[NOI2009]管道取珠】


    ——(shallwe):这道题是(noipDay2T2)难度

    好一个(Day2T2)难度啊,我觉得我可以退役了

    平方和好像没有什么办法可以快速统计,于是考虑转化一下

    我们可以将题意转化成这样

    求有序对((A,B)),取法(A)可以和取法(B)得到相同的结果

    也就是可以将题目抽象成一个人进行这个游戏两遍,能得到同样结果的方案数是多少

    之后我们可以设计出这样的(dp)方程,(dp[i][j][k][p])表示第一次取从上面那个管道里取出了(i)个,从下面那个管道里取出了(j)个,第二次从上面那个管道取出(k)个,从第二个管道里取出(p)个,得到的结果相同的方案数

    结果相同肯定得取出的数量相同,所以(i+j=k+p),于是(p)那一维可以不要了

    同时我们还可用滚掉一维,进一步优化空间

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 505
    const int mod=1024523;
    int n,m,o;
    char A[maxn],B[maxn];
    char a[maxn],b[maxn];
    int dp[2][maxn][maxn];
    inline int qm(int a,int b)
    {
    	int t=a+b;
    	if(t>mod) return t-mod;
    	return t;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	scanf("%s",A+1);
    	scanf("%s",B+1);
    	for(re int i=1;i<=n;i++) a[i]=A[n-i+1];
    	for(re int j=1;j<=m;j++) b[j]=B[m-j+1];
    	dp[0][0][0]=1;
    	for(re int i=0;i<=n;i++,o^=1)
    		for(re int j=0;j<=m;j++)
    			for(re int k=0;k<=n;k++)
    			{
    				int p=i+j-k;
    				if(p<0||p>m) continue;
    				if(a[i+1]==a[k+1]) dp[o^1][j][k+1]=qm(dp[o^1][j][k+1],dp[o][j][k]);
    				if(b[j+1]==b[p+1]) dp[o][j+1][k]=qm(dp[o][j+1][k],dp[o][j][k]);
    				if(a[i+1]==b[p+1]) dp[o^1][j][k]=qm(dp[o^1][j][k],dp[o][j][k]);
    				if(b[j+1]==a[k+1]) dp[o][j+1][k+1]=qm(dp[o][j+1][k+1],dp[o][j][k]);
    				dp[o][j][k]=0;
    			}
    	std::cout<<dp[o][m][n];
    	return 0;
    }
    
  • 相关阅读:
    [Hibernate]
    asc.desc
    Could not obtain connection metadata
    java枚举类Enum方法简介(valueof,value,ordinal)
    maven3 手动安装本地jar到仓库
    maven命令大全
    如何正确遍历删除List中的元素,你会吗?
    Hibernate的session.createSQLQuery的几种查询方式
    Linux-github 搭建静态博客
    我所写的CNN框架 VS caffe
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205727.html
Copyright © 2020-2023  润新知