Solution - Qoj17158 Palindromes

主观难度:【3】

我做几把。


答案显然是 \(2^{连通块个数} \bmod m\)。考虑怎么求连通块个数。

当最大和次大限制 \(x, y\) 满足 \(x \ge 2y\) 那么显然存在 \(\lceil \frac x 2 \rceil - y\) 个自由元。

考虑一个结论,即对于两个限制 \(x, y(x < 2y)\),两个限制均成立的一个充要条件是 \(y, (2y-x)\) 成立。我们可以把这个东西放进一个堆然后维护即可,但是会 T。

我们发现 \(x - y = y - (2y-x)\),那么我们可以设 \(\Delta = x-y\),对 \(x, y\) 一直减去 \(\Delta\),直到 \(y\) 即将失去次大值资格。我们可以使用除法来实现这一点。发现在这时如果 \(x \ge 2y\) 当且仅当 \(y \le \Delta\)。然后搞就行了。

复杂度证明:我不会。

#include <bits/stdc++.h>
#define llong long long
#define N 500005
using namespace std;

#define bs (1<<20)
char buf[bs], *p1, *p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,bs,stdin),p1==p2)?EOF:*p1++)
template<typename T>
inline void read(T& x){
    x = 0; int w = 1;
    char ch = gc();
    while(ch < '0' || ch > '9'){
        if(ch == '-') w = -w;
        ch = gc();
    }
    while(ch >= '0' && ch <= '9')
        x = (x<<3)+(x<<1)+(ch^48), ch = gc();
    x *= w;
}
template<typename T, typename ...Args>
inline void read(T& x, Args& ...y){
    return read(x), read(y...);
}

int n; llong m, p;
llong res, x;
priority_queue<llong> pq;

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

int main(){
    read(m, n, p);
    pq.push(0);
    for(int i = 1; i <= n; ++i) read(x), pq.push(x);
    res += m-pq.top();
    while(pq.size()){
        llong x = pq.top(); pq.pop();
        if(!x || x == pq.top()) continue;
        llong y = pq.top(); pq.pop();
        if(x < 2*y){
            llong z = pq.top();
            llong delta = x-y, t = (y-z)/delta;
            x -= t*delta, y -= t*delta;
            if(x >= 2*y) res += ((x+1)>>1)-y, pq.push(y);
            else pq.push(x-delta), pq.push(y-delta);
        }
        else
            res += ((x+1)>>1)-y, pq.push(y);
    }
    printf("%lld", qpow(2, res));
    return 0;
}

posted @ 2026-03-27 22:27  Hootime  阅读(4)  评论(0)    收藏  举报