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;
    }
    

      

  • 相关阅读:
    从坐标系图中理解“空间变换”
    Normal Map中的值, Tangent Space, 求算 Tangent 与 Binormal 与 TBN Matrix
    A Personal Understanding to Matrix Transformation in Graphics
    [转] 双数组前缀树
    [转] Hive简介
    [转] 远程访问服务器Jupyter Notebook的两种方法
    [转] LSTM中的pack和pad
    [转] Beam Search
    [转] linux提示符过长tips
    [转] batch normalization相关
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/12636904.html
Copyright © 2011-2022 走看看