• [BZOJ1566][NOI2009]管道取珠


    [BZOJ1566][NOI2009]管道取珠

    试题描述

     

    输入

    第一行包含两个整数n, m,分别表示上下两个管道中球的数目。 第二行为一个AB字符串,长度为n,表示上管道中从左到右球的类型。其中A表示浅色球,B表示深色球。 第三行为一个AB字符串,长度为m,表示下管道中的情形。

    输出

    仅包含一行,即为 Sigma(Ai^2) i从1到k 除以1024523的余数。

    输入示例

    2 1
    AB
    B

    输出示例

    5

    数据规模及约定

    约30%的数据满足 n, m ≤ 12; 
    约100%的数据满足n, m ≤ 500。

    题解

    这题思路比较妙,我们需要先想想 ∑ai2 有什么意义。如果我们构造出这样一个游戏场景,即两个人同时玩两份同样的如题目所述的管道取珠的游戏,那么这两个人游戏结束后取到的珠子颜色序列一模一样的方案数就是题目里要求的答案。

    令这两个人分别是 p1 和 p2。于是设 f[i][j][k] 表示 p1 取了第二个管道中的前 i 个珠子,第一个管道中的前 j 个珠子;p2 取了第一个管道的前 k 个珠子,这个状态下颜色序列相同的方案数,转移显然。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 510
    #define MOD 1024523
    int n, m, f[2][maxn][maxn];
    bool has[2][maxn][maxn];
    char A[maxn], B[maxn];
    
    int main() {
    	n = read(); m = read();
    	scanf("%s%s", A + 1, B + 1);
    	
    	int cur = 0;
    	f[0][0][0] = 1; has[0][0][0] = 1;
    	for(int i = 0; i <= m; i++, cur ^= 1) {
    		for(int j = 0; j <= n; j++)
    			for(int k = 0; k <= n; k++) f[cur^1][j][k] = has[cur^1][j][k] = 0;
    		for(int j = 0; j <= n; j++)
    			for(int k = 0; k <= n; k++) if(has[cur][j][k]) {
    //				printf("%d %d %d: %d
    ", i, j, k, f[cur][j][k]);
    				int bj = i, bk = i + j - k;
    				if(j < n && k < n && A[j+1] == A[k+1]) {
    					f[cur][j+1][k+1] += f[cur][j][k]; has[cur][j+1][k+1] = 1;
    					if(f[cur][j+1][k+1] >= MOD) f[cur][j+1][k+1] -= MOD;
    				}
    				if(j < n && bk < m && A[j+1] == B[bk+1]) {
    					f[cur][j+1][k] += f[cur][j][k]; has[cur][j+1][k] = 1;
    					if(f[cur][j+1][k] >= MOD) f[cur][j+1][k] -= MOD;
    				}
    				if(bj < m && k < n && B[bj+1] == A[k+1]) {
    					f[cur^1][j][k+1] += f[cur][j][k]; has[cur^1][j][k+1] = 1;
    					if(f[cur^1][j][k+1] >= MOD) f[cur^1][j][k+1] -= MOD;
    				}
    				if(bj < m && bk < m && B[bj+1] == B[bk+1]) {
    					f[cur^1][j][k] += f[cur][j][k]; has[cur^1][j][k] = 1;
    					if(f[cur^1][j][k] >= MOD) f[cur^1][j][k] -= MOD;
    				}
    			}
    	}
    	
    	printf("%d
    ", f[cur^1][n][n]);
    	
    	return 0;
    }
    
  • 相关阅读:
    更改PHP配置文件php.ini解决xmlhttp的utf8乱码
    php 单引号 双引号 区别
    zend soap looks like we got no XML document
    使用UltraEdit32编辑器格式化源码功能 XML、Java、C/C++、C#
    php str_replace 单引号 双引号 区别
    PHP将XML文件转换成PHP数组
    简述PHP4和PHP5版本下解析XML文档的操作方法
    HowTo: Fix SimpleXML CDATA problem in php
    XML中 CDATA and PCDATA 的区别
    php 生成xml 的四种方式
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6402793.html
Copyright © 2020-2023  润新知