传送门

Solution

A0A_0 所有元素之和为 sumsum

sum0sum \le 0 ,答案为 00

sum>0sum>0,因为 A0A_0 各项均不大于 11,则一定存在 kk,使得 A0A_0 经过 kk 次循环左移后,A0A_0 是安全的,且此时可把 A0A_0 分为 sumsum 块,每一块的元素之和都恰好为 11。以样例循环左移三次后为例:

1 1 -1 0 | 1 1 1 -2

此时两部分之和分别都为 11

所以对于满足 sum>0sum>0 的任意 A0A_0,其实可以把它分成 sumsum 块整体,循环左移时一块一块地捆绑在一起。这样 A0A_0 循环左移的结果只有 sumsum 种,且显然它们都是安全的数列。而且易证对于确定的 A0A_0,捆绑的方式只有一种,循环左移后的数列也只有 sumsum 个是安全的。

AiA_i 的长度为 pip_i 倍的 A0A_0,取 p0=1p_0=1,有

pi+1=pi2sump_{i+1}=p_{i}^2sum

这个递推公式可以通过手玩得到。由它又可推出答案

pi+1pi=sum2k\dfrac{p_{i+1}}{p_i}=sum^{2^k}

M=998244353M=998244353,因为 kk 最大为 10610^6,且要对 MM 取模,用扩展欧拉定理可得

\dfrac{p_{i+1}}{p_i}=sum^{2^k}=sum^{2^k\bmod {M-1}}\bmod M

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll N = 1e6 + 10, mod = 998244353;

ll n, a[N], k, sum[N], ans = 0, low, cnt, len, minn[N], mini, tot;
priority_queue<int> q;

ll qpow(ll a, ll b, ll p)
{
    ll res = 1;
    while (b) {
        if (b & 1) res = res * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return res;
}

int main()
{
    scanf("%lld%lld", &n, &k);
    len = 1;
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
        sum[i] = sum[i - 1] + a[i];
    }
    if (sum[n] <= 0) {
        printf("0");
        return 0;
    }
    printf("%lld", qpow(sum[n], qpow(2, k, mod - 1), mod));
    return 0;
}