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

浙公网安备 33010602011771号