zoukankan      html  css  js  c++  java
  • 【[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;
    }
    
  • 相关阅读:
    向eureka注册正确的ip地址
    sleuth + zipkin 链路分析
    Yii2的整体结构概览
    Redis实现消息队列
    Redis使用场景梳理
    redis基础知识
    TCP服务
    数据结构-队列
    看见
    线性表的链式存储结构
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205727.html
Copyright © 2011-2022 走看看