zoukankan      html  css  js  c++  java
  • Problem Palindrome

     

     这道题容斥想了半天。。。

    拉丁字母共 52个 2^52 = 4e15, 不会爆long long,于是先给字母编号

    inline int calc(char c)
    {
        if (c < 'a') return c - 'A';
        return (c - 'a' + 26);
    }
    

      

    这样对于当前状态 ll res, res的二进制第i位(以下进制都是二进制)为1表示标号为(i-1)的字母出现了奇数次

    这样我们就可以

    1.把状态相等的 res,归为一类,这一类对答案的贡献就是 size * (size - 1) / 2

    2.然而不光是同类相减出现回文串,只要两个状态相差一个字母的奇偶不同相减就可以产生一个答案,所以我们还要让每个集合与相邻的集合去对答案做贡献

    3.对于不靠状态相减就能对答案做贡献的只有 res = 0 或 1

    对于单个字母,都是靠相减剪出来的(比如第i(i != 1)个字母,是靠res(i) - res(i - 1)剪出来对答案做贡献的 条件2)(对于第一个字母,是由 条件3对答案做贡献的)

    具体实现见代码

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int maxn = 2e5 + 5;
    
    int n, f[maxn], siz[maxn], cnt[52];
    char s[maxn];
    map<ll, int> mp;
    vector<ll> ve[49];
    
    inline int calc(char c)
    {
        if (c < 'a') return c - 'A';
        return (c - 'a' + 26);
    }
    
    void unit(int x, int y)
    {
        f[y] = x;
        ++siz[x];
    }
    
    int main()
    {
        scanf("%d%s", &n, s + 1);
        int flag = 0; ll res = 0, ans = 0;
        for (int i = 1; s[i]; ++i)
        {
            f[i] = i, siz[i] = 1;
            int id = calc(s[i]);
            if (++cnt[id] % 2) ++flag;
            else --flag;
            if (flag <= 1) ++ans; //条件3
            res ^= 1ll << id;
            if (!mp.count(res)) mp[res] = i, ve[flag].emplace_back(res);
            else  unit(mp[res], i);
        }
        if (!ve[0].empty())
        {
            int id = mp[ve[0][0]];
            ans += (ll)siz[id] * (siz[id] - 1) >> 1; //条件1
        }
        for (int i = 48; i; --i)
        {
            for (int j = 0; j < ve[i].size(); ++j)
            {
                res = ve[i][j]; int id = mp[res];
                ans += (ll)siz[id] * (siz[id] - 1) >> 1; //条件1
                for (int k = 0; k < 52; ++k)
                    if (res & (1ll << k))
                    {
                        ll r = res ^ (1ll << k);
                        if (mp.count(r) == 0) continue;
                        ans += (ll)siz[id] * siz[mp[r]];  //条件2
                    }
            }
        }
        printf("%lld", ans);
        return 0;
    }
    

      

  • 相关阅读:
    php if() 括号中为 真详解
    php 写入日志
    trim,rtrim,ltrim详解
    SQlite3 的简单用法。 调用本地时间
    RuntimeError at /host You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your fo
    D3.js 入门系列3
    js中const,var,let区别
    D3.js 入门系列2 — 选择元素和绑定数据
    D3.js 入门系列1
    SVG 教程03
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12636904.html
Copyright © 2011-2022 走看看