2021杭电多校4 1003/HDU 6987 Cycle Binary

题目链接:https://acm.hdu.edu.cn/showproblem.php?pid=6987

题目大意:01串\(S\)可分割为\(kp+p'\),其中\(p'\)\(p\)的部分前缀,定义最大循环次数\(k\)\(v(s)\),计算长度为\(n\)的01串\(S\)\(v(S)\)的和

题目思路:
定义\(f(x)\)为长度为\(n\)\(v(S)\)\(x\)的01串个数
则答案

\[ans=\sum_{x=1}^{n}\left \lfloor \frac{n}{x} \right \rfloor f(x) \]

长度为\(x\)的01串\(T\)共有\(2^x\)种情况,其中存在周期\(y(y<x,y\mid x)\)的情况显然不能被计算到\(f(x)\)中,所以我们猜测

\[f(x) = 2^x-\sum_{y\mid x,y<x}^{}f(y) \]

证明:
根据周期引理:若\(x,y\)是字符串\(S\)的周期且\(x+y-gcd(x,y)\leq |S|\),则\(gcd(x,y)\)也是\(S\)的一个周期,此处的\(x+y-gcd(x,y)\leq |S|\)等价于\(x\leq\frac{n}{2}\)
\(x\leq\frac{n}{2}\)时,假设\(T\)不存在周期\(y(y<x,y\mid x)\),而\(S\)有一个更小的周期\(y\),根据周期引理,\(gcd(x,y)\)也是\(S\)的一个周期,同时\(gcd(x,y)\mid x\),因此\(gcd(x,y)\)也是\(T\)的一个周期,与我们假设的\(T\)相悖,因此\(x\)才是\(S\)的最小周期,可以用\(f(x) = 2^x-\sum_{y\mid x,y<x}^{}f(y)\)计算
\(x > \frac{n}{2}\)时,\(f(x)\)的系数都是1,用总串数\(2^n-[x\leq\frac{n}{2}]\)的串数即可,公式可化为

\[ans =\sum_{x=1}^{\frac{n}{2}}\left \lfloor \frac{n}{x} \right \rfloor f(x) + 2^n - \sum_{x=1}^{\frac{n}{2}} f(x)\\ =2^n+\sum_{x=1}^{\frac{n}{2}}(\left \lfloor \frac{n}{x} \right \rfloor-1)f(x) \]

可用分块计算,其中\(f(x)\)前缀和可用杜教筛计算

\[f(x) = 2^x-\sum_{y\mid x,y<x}^{}f(y)\Rightarrow 2^x = \sum_{y\mid x}^{}f(y)=f*1 \]

AC代码:

#include <unordered_map>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <string>
#include <stack>
#include <deque>
#include <queue>
#include <cmath>
#include <map>
#include <set>
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int N = 4e6 + 10, M = 31 * N;
const int max_n = 1e7 + 10;
const int base = 1e9;
const int P = 131;
const int mod = 998244353;
const double eps = 1e-8;
const double PI = acos(-1.0);
unordered_map<int, int> ans_f;
int f[N];
void init(int n)
{
    int pow2 = 1;
    for (int i = 1; i < n; ++i)
    {
        pow2 = (ll)pow2 * 2 % mod;
        f[i] = pow2;
    }
    for (int i = 1; i < n; ++i)
        for (int j = 2 * i; j < n; j += i)
            f[j] = (f[j] - f[i] + mod) % mod;
    for (int i = 1; i < n; ++i)
        f[i] = (f[i] + f[i - 1]) % mod;
}
int ksm(int a, int b)
{
    int res = 1 % mod;
    while (b)
    {
        if (b & 1)
            res = (ll)res * a % mod;
        a = (ll)a * a % mod;
        b >>= 1;
    }
    return res;
}
int Sf(int n)
{
    if (n < N)
        return f[n];
    if (ans_f.count(n))
        return ans_f[n];
    int res = ksm(2, n);
    for (int l = 2, r; l <= n; l = r + 1)
    {
        r = min(n, n / (n / l));
        res = (res - (ll)(r - l + 1) * Sf(n / l) % mod + mod) % mod;
    }
    return ans_f[n] = res;
}
int main()
{
    init(N - 1);
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        int ans = ksm(2, n);
        int pre = 0;
        for (int l = 1, r; l <= n / 2; l = r + 1)
        {
            r = min(n, n / (n / l));
            int now = Sf(r);
            ans = (ans + (ll)(now - pre + mod) % mod * (n / l - 1) % mod) % mod;
            pre = now;
        }
        printf("%d\n", ans);
    }
    return 0;
}

posted @ 2021-08-12 18:12  xiaopangpang7  阅读(107)  评论(0编辑  收藏  举报