zoukankan      html  css  js  c++  java
  • 「JSOI2016」无界单词

    题目描述

    对于一个单词 $S$ ,如果存在一个长度 $l$,满足 $0lt llt |S|$,并且使得 $S$ 长度为 $l$ 的前缀与 $S$ 长度为 $l$ 的后缀相同,JYY 则称 $S$ 是有界的。比如 `aabaa` 和 `ababab` 就都是有界的字符串。如果一个单词不存在这样的 $l$ ,则 JYY 称之为无界单词。

    现在考虑所有仅由字母 `a` 和 `b` 组成的长度为 $N$ 的字符串,JYY想知道:
    1. 一共有多少个无界单词?
    2. 这些无界单词中,按字典序排列第 $K$ 小的单词是哪一个?

    数据范围

    对于全部数据,满足 $1le Tle 5,1le Nle 64$ ,并且保证对于任意测试数据,总存在第 $K$ 小的无界单词。

    题解

    考虑到每个有界单词总是能表示成两个无界单词放在首位且长度不超过该有界单词的一半。

    于是可以考虑 $dp$ , $f_i$ 表示长度为 $i$ 的无界单词的个数,转移考虑容斥即可。

    第二问只需要按位考虑即可,将 $dp$ 状态表示成长度为 $i$ ,且前 $len$ 为已经确定的无界单词的个数,转移是类似的。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    #define U unsigned long long
    const int N=70;
    const U B=793999;
    int T,n,a[N];
    U k,f[N],b[N],g[N];
    U H(int l,int r){
        return g[r]-g[l-1]*b[r-l+1];
    }
    bool J(int x){
        for (int i=1;i<x;i++)
            if (H(1,i)==H(x-i+1,x))
                return 0;
        return 1;
    }
    void work(){
        cin>>n>>k;
        f[1]=2;
        for (int i=2;i<=n;i++) f[i]=0;
        for (int i=2;i<=n;i++){
            for (int j=1;j+j<=i;j++)
                f[i]+=f[j]*((U)1<<(i-j-j));
            f[i]=((U)1<<i)-f[i];
        }
        if (n==64) f[n]--;
        cout<<f[n]<<endl;
        for (int h=1;h<=n;h++){
            g[h]=g[h-1]*B+1;a[h]=0;
            for (int i=1;i<=n;i++) f[i]=0;
            for (int i=1;i<=h;i++)
                if (J(i)) f[i]=1;
            for (int i=h+1;i<=n;i++){
                for (int j=1;j+j<=i;j++){
                    if (i-j+1<=h){
                        if (H(1,h-i+j)==H(i-j+1,h))
                            f[i]+=f[j];
                    }
                    else f[i]+=f[j]*((U)1<<(i-j-max(j,h)));
                }
                f[i]=((U)1<<(i-h))-f[i];
            }
            if (f[n]<k) a[h]++,k-=f[n];
            putchar(a[h]+97);
            g[h]=g[h-1]*B+a[h]+1;
        }
        putchar('
    ');
    }
    int main(){
        b[0]=1;
        for (int i=1;i<N;i++) b[i]=b[i-1]*B;
        for (scanf("%d",&T);T--;work());
        return 0;
    }
  • 相关阅读:
    T-SQL:Varchar和Nvarchar区别(八)
    UI5-文档-4.1-Hello World!
    UI5-文档-4-Walkthrough
    UI5-文档-3-Hello World!
    UI5-文档-2.5-开发混合Web容器
    UI5-文档-2.4-Node.js-Based开发环境
    UI5-文档-2.3-使用SAPUI5工具为Eclipse开发应用程序
    UI5-文档-2.2-使用SAP Web IDE开发应用程序
    UI5-文档-2.1-使用OpenUI5开发应用
    UI5-文档-2-开发环境
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11779182.html
Copyright © 2011-2022 走看看