首页 > 其他分享 >D - Avoid K Palindrome

D - Avoid K Palindrome

时间:2024-07-07 18:52:28浏览次数:7  
标签:Palindrome int Avoid abc359 ll dp

D - Avoid K Palindrome

https://atcoder.jp/contests/abc359/tasks/abc359_d

 

思路

https://atcoder.jp/contests/abc359/submissions/54822869

状压DP

以 K二进制位表示 K字符串(由AB组成), 判断并记录是否为回文。

dp[i][j]  -- 前i个字符,如果以j(k字符状压表示)结尾,是good string的可能字符串个数。

初始化前K位dp

计算后续dp。

code

https://atcoder.jp/contests/abc359/submissions/55346351

typedef long long ll;
const ll mod = 998244353;

ll n, k;
string s;

const ll nsize = 1005;
const ll kstatesize = 1<<10 + 5;
bool mirror[kstatesize];

ll dp[nsize][kstatesize];

/*
    kseq is represented by bitseq of k bit length
    10101011111111
    this function is to check if it is of mirror structure
    mirror structure has central symmetry, for example
    101
    11011
*/
bool checkmirror(ll kseq){
    /*
    iterate from 0 positon to half position k>>1
    1111111111111111111111111111
        l                  r
    */
    for(int i=0; i<(k>>1); i++){
        ll l = i;
        ll r = k - i -1;

        ll lbit = (kseq>>l)&1;
        ll rbit = (kseq>>r)&1;

        if (lbit != rbit){
            return false;
        }
    }

    return true;
}

int main()
{
    cin >> n >> k;
    cin >> s;

    for(int i=0; i<(1<<k); i++){
        mirror[i] = checkmirror(i);
    }

    /*
    initialize the first k seq of dp
    */
    for(int i=0; i<(1<<k); i++){
        // only non-mirror seq takes effect
        if (mirror[i]){
            continue;
        }

        /*
        suppose the first k seq follow the i case
        increase dp
        */
        dp[k-1][i]++;

        /*
        then detect if any break with i case,
        if yes, decrease dp
        */
        for(int j=0; j<k; j++){
            /*
            in i case, for each bit,
            0    --    A
            1   --  B
            */
            ll jbitpos = k - j - 1;
            ll jbit = (i>>jbitpos)&1;

            if (s[j]=='A' && jbit==1){
                dp[k-1][i]--;
                break;
            }

            if (s[j]=='B' && jbit==0){
                dp[k-1][i]--;
                break;
            }
        }
//        cout<<dp[k-1][i];
    }

    /*
    now iterate from k to n-1 to calculate the following dp
    */
    for(int i=k; i<n; i++){
        /*
        iterate each non-mirror cases
        */
        for(int j=0; j<(1<<k); j++){
            // as of this case j, the previous state i-1 is not a good string
            // i.e. dp == 0
            // for the new added char of i index, the new string is still not a good string
            // so skip
            if (dp[i-1][j] == 0){
                continue;
            }

            // if the new added char of i index is not A,
            // the possible value is B or ?
            // let's make the possible state transfer
            if (s[i]!='A'){
                // newk is appended by B, and removed the left-most char
                ll newk = ((j<<1)|1)&((1<<k)-1);
//                cout<<newk;
                // if newk is not mirror, the new string is a good string
                // newk is not mirror, make state stranfer
                if (!mirror[newk]){
                    dp[i][newk] = (dp[i][newk] + dp[i-1][j]) % mod;
                }
            }

            // if the new added char of i index is not B,
            // the possible value is A or ?
            // let's make the possible state transfer
            if (s[i]!='B'){
                // newk is appended by A, and removed the left-most char
                ll newk = (j<<1)&((1<<k)-1);
//                cout<<newk;
                // if newk is not mirror, the new string is a good string
                // newk is not mirror, make state stranfer
                if (!mirror[newk]){
                    dp[i][newk] = (dp[i][newk] + dp[i-1][j]) % mod;
                }
            }
        }
//        for(int j=0;j<(1<<k);j++)cout<<dp[i][j];
//        cout<<'\n';
    }

    // now we get dp[n-1],
    // let calculate total number of all states
    ll ans = 0;
    for(int i=0; i<(1<<k); i++){
        ans = (ans + dp[n-1][i]) % mod;
//        cout<<dp[n-1][i];
    }

    cout << ans << endl;

    return 0;
}

 

标签:Palindrome,int,Avoid,abc359,ll,dp
From: https://www.cnblogs.com/lightsong/p/18288798

相关文章

  • P6754 [BalticOI 2013 Day1] Palindrome-Free Numbers
    数据范围一眼数位dp。关键条件为如果一个数字串的一个长度大于 11 的子串也为回文串的话,那么我们也定义这个数字串为回文串。仔细思考发现一旦两个连续的数相同(偶回文)或两个数隔一个数相同(奇回文)都是回文,所以要保证连续三个数不相同,记录前两位即可。注意事项:1.前导零不应为0......
  • [Vue warn]: Avoid mutating a prop directly since the value will be overwritten v
    [Vuewarn]:Avoidmutatingapropdirectlysincethevaluewillbeoverwrittenwhenevertheparentcomponentre-renders.Instead,useadataorcomputedpropertybasedontheprop'svalue.Propbeingmutated:"dialogVisibleEdits"这个警告信息是Vu......
  • Cobra - How to avoid access global variables in a global variable or init() func
    在同一个package中的init()函数是按照所在文件文件名的字母顺序执行的,如果一个文件排在root.go之前,那么在其中字义的<文件名>Cmd全局变量赋值时将不能使用在root.go中初始化并赋值的全局变量(如globalflags),同样在其init()函数中也不能使用那些全局变量,如果使用则会报空指针错误。......
  • [题解]CF245H Queries for Number of Palindromes
    思路定义\(dp_{i,j}\)表示区间\([i,j]\)中回文串的数量。那么,不难得出状态转移方程\(dp_{i,j}=dp_{i-1}+f_{i,j}\)。(其中\(f_{i,j}\)表示左端点大于等于\(i\),右端点为\(j\)的回文串数量)由此,现在问题转变为了如何求\(f_{i,j}\)。如果我们在求出了\(f_{i+1,j}......
  • [AGC001D] Arrays and Palindrome
    题意有长度为\(n\)的字符串\(S\),与\(a,b\)两个序列。满足\(\suma_i=n,\sumb_i=n\)。若满足\(S\)的以下子段都为回文串:最前面的\(a_1\)个字符,以及紧接着的\(a_2\)个字符...最前面的\(b_1\)个字符,以及紧接着的\(b_2\)个字符...则\(S\)的所有字符......
  • LeetCode 409 Longest Palindrome All In One
    LeetCode409LongestPalindromeAllInOneLeetCode409最长回文算法题解Solutions//MapfunctionlongestPalindrome(s:string):number{constmap=newMap();letlen=0;for(leti=0;i<s.length;i++){if(map.has(s[i])){//配对,消元......
  • Day 9:2829. k-avoiding 数组的最小总和
    Leetcode2829.k-avoiding数组的最小总和给你两个整数n和k。对于一个由不同正整数组成的数组,如果其中不存在任何求和等于k的不同元素对,则称其为k-avoiding数组。返回长度为n的k-avoiding数组的可能的最小总和。n个不同正整数的最小总和,那就是从1......
  • 机器学习策略篇:详解可避免偏差(Avoidable bias)
    可避免偏差如果希望学习算法能在训练集上表现良好,但有时实际上并不想做得太好。得知道人类水平的表现是怎样的,可以确切告诉算法在训练集上的表现到底应该有多好,或者有多不好,让我说明是什么意思吧。经常使用猫分类器来做例子,比如人类具有近乎完美的准确度,所以人类水平的错误是1%......
  • ABC 286 C - Rotate and Palindrome
    题目链接:注意到“您可以按任意顺序执行以下两种运算零次或多次”。因此,解决这个问题的一个重要观察点是,你可以假设\(A\)操作执行了几次,然后\(B\)操作执行了几次。你也可以假设\(A\)操作最多被执行\(N\)次(因为执行\(N\)次就会使它处于原始状态)有了这个观察结果,你就......
  • Rust Reference Cycles: Resolving and Avoiding them
    InRust,referencecyclesoccurwhentwoormoreobjectsmutuallyreferenceeachother,formingacircularchain.Inthissituation,thereferencecountbetweenobjectsneverbecomeszero,leadingtomemoryleaksandresourceleaks.Thisblogpostwilldi......