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} ight floor f(x) ]

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

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

[ans =sum_{x=1}^{frac{n}{2}}left lfloor frac{n}{x} ight floor 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} ight floor-1)f(x) ]

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

[f(x) = 2^x-sum_{ymid x,y<x}^{}f(y)Rightarrow 2^x = sum_{ymid 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
", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/xiaopangpangdehome/p/15134111.html