• [NOI2009]管道取珠


    链接P1758 [NOI2009]管道取珠

    • 要肝出这道题,你需要知道这样一个(trick.)
    • 如果你要求对于一个什么东西求出现次数的平方,等价于同时进行两次操作,计算过程可以匹配的方案数。
    • 这个(trick)可以去某次神仙(yyb)的暑假一次(noip)模拟赛学一下。
    • 话说(yyb)那一次是真的毒瘤。话说神仙(fdf)当场爆切。
    • 那么$ ∑A_i^2$,可以看成取两次得到了相同的串的方案数。
    • 这样就很套路了,朴素想法设(f_{i,j,p,q})表示第一次(a)串在(i)(b)串在(j)位置,第二次(a)串在(p)(b)串在(q)位置。
    • 很显然(i+j=p+q),那么后面一维度就省掉了,设(f_{i,j,k})表示总长度为(i),第一次(a)串在(j),第二次(a)串在(k)的方案数。
    • 随便讨论转移一下即可,初始(f_{0,0,0}=1),复杂度(O(n^3))
    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    const int N=601;
    const int mod=1024523;
    int n,m,f[2][N][N];char A[N],B[N];
    void add(R &x,R y){x=(x+y>=mod?x+y-mod:x+y);}
    int main(){
        cin>>n>>m,scanf("%s",A+1),scanf("%s",B+1);
        reverse(A+1,A+n+1),reverse(B+1,B+m+1);
        R now=1,pre=0;f[now][0][0]=1;
        for(R len=1;len<=n+m;++len){
            now^=1,pre^=1;
            for(R i=max(0,len-m);i<=min(n,len);++i)
                for(R j=max(0,len-m);j<=min(n,len);++j)
                    f[now][i][j]=0;
            for(R i=max(0,len-m);i<=min(n,len);++i){
                for(R j=max(0,len-m);j<=min(n,len);++j){
                    R p=len-i,q=len-j;
                    if(i&&j&&A[i]==A[j])add(f[now][i][j],f[pre][i-1][j-1]);
                    if(i&&q&&A[i]==B[q])add(f[now][i][j],f[pre][i-1][j]);
                    if(p&&j&&B[p]==A[j])add(f[now][i][j],f[pre][i][j-1]);
                    if(p&&q&&B[p]==B[q])add(f[now][i][j],f[pre][i][j]);
                }
            }
        }
        cout<<f[now][n][n]<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    laravel 使用构造器进行增删改查
    explan各项说明
    data函数参数
    php引用
    PHP开发api接口安全验证方法一
    redis主从配置
    php 实现同一个账号同时只能一个人登录
    MySQL慢查询1- 开启慢查询
    前端基础 & 初识HTML
    HTTP协议概述
  • 原文地址:https://www.cnblogs.com/Tyher/p/9902039.html
Copyright © 2020-2023  润新知