题解 [UNR #6] 小火车
只会 \(O(3^{\frac{n}{2}})\)
数据随机那档 meeting in middle 的时候在两边多随点状态就行了
但是我看错时限卡时卡错了,寄
然后正解:
首先发现本题一定有解
证明考虑鸽巢原理,有 \(2^n>p\) 种可能,那么一定存在两个集合权值相等
- 关于「权值相同的无交集合」:
一个常见 trick 是无交的限制无意义。找到两个权值相同的集合,删去公共部分即可得到两个权值相同的无交集合
那么这个题就是要找两个权值相同的无交集合
那么可以二分找出一个对应了多个集合的权值 \(mid\),check 可以 meet in middle 后每次双指针
然后找到一个 \(mid\) 后找方案也是同样的方法
复杂度 \(O(2^{\frac{n}{2}}\log n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 10000010
#define fir first
#define sec second
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline ll read() {
ll ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
ll n, p;
ll a[100];
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a,b>>=1) if (b&1) ans=ans*a; return ans;}
pair<ll, ll> sta1[N], sta2[N];
int tem[100], top1, top2, siz1, siz2;
namespace force{
inline void decode1(ll s) {for (int i=1; i<=siz1; ++i) tem[i]=s%3, s/=3;}
inline void decode2(ll s) {for (int i=1; i<=siz2; ++i) tem[i]=s%3, s/=3;}
void solve() {
siz1=n>>1, siz2=n-siz1;
int lim1=qpow(3, siz1), lim2=qpow(3, siz2);
for (int s=0; s<lim1; ++s) {
decode1(s);
ll val=0;
for (int i=1; i<=siz1; ++i)
if (tem[i]==1) val+=a[i];
else if (tem[i]==2) val+=p-a[i];
// assert(val>=0);
sta1[++top1]={val%p, s};
}
for (int s=0; s<lim2; ++s) {
decode2(s);
ll val=0;
for (int i=1; i<=siz2; ++i)
if (tem[i]==1) val+=a[siz1+i];
else if (tem[i]==2) val+=p-a[siz1+i];
// assert(val>=0);
sta2[++top2]={val%p, s};
}
sort(sta1+1, sta1+top1+1);
sort(sta2+1, sta2+top2+1);
// cout<<"sta1: "; for (int i=1; i<=top1; ++i) cout<<"("<<sta1[i].fir<<','<<sta1[i].sec<<") "; cout<<endl;
int p1=1, p2=1;
for (; p1<top1&&!sta1[p1+1].fir; ++p1);
for (; p2<top2&&!sta2[p2+1].fir; ++p2);
if (p1!=1||p2!=1) {
decode1(sta1[p1].sec);
for (int i=1; i<=siz1; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
decode2(sta2[p2].sec);
for (int i=1; i<=siz2; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
printf("\n");
exit(0);
}
for (int p1=1,p2=top2; p1<=top1; ++p1) {
for (; p2>1&&sta1[p1].fir+sta2[p2].fir>p; --p2);
if (sta1[p1].fir+sta2[p2].fir==p) {
decode1(sta1[p1].sec);
for (int i=1; i<=siz1; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
decode2(sta2[p2].sec);
for (int i=1; i<=siz2; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
printf("\n");
exit(0);
}
}
puts("IMPOSSIBLE");
}
}
namespace task1{
random_device seed;
mt19937_64 rand(seed());
inline void decode1(ll s) {for (int i=1; i<=siz1; ++i) tem[i]=s%3, s/=3;}
inline void decode2(ll s) {for (int i=1; i<=siz2; ++i) tem[i]=s%3, s/=3;}
void solve() {
siz1=n>>1, siz2=n-siz1;
ll lim1=qpow(3, siz1), lim2=qpow(3, siz2);
for (int i=1; i<=2000000; ++i) {
ll s=rand()%lim1;
decode1(s);
ll val=0;
for (int i=1; i<=siz1; ++i)
if (tem[i]==1) val+=a[i];
else if (tem[i]==2) val+=p-a[i];
// assert(val>=0);
sta1[++top1]={val%p, s};
}
for (int i=1; i<=2000000; ++i) {
ll s=rand()%lim2;
decode2(s);
ll val=0;
for (int i=1; i<=siz2; ++i)
if (tem[i]==1) val+=a[siz1+i];
else if (tem[i]==2) val+=p-a[siz1+i];
// assert(val>=0);
sta2[++top2]={val%p, s};
}
sort(sta1+1, sta1+top1+1);
sort(sta2+1, sta2+top2+1);
// cout<<"sta1: "; for (int i=1; i<=top1; ++i) cout<<"("<<sta1[i].fir<<','<<sta1[i].sec<<") "; cout<<endl;
int p1=1, p2=1, pos1=0, pos2=0;
for (; p1<top1&&!sta1[p1+1].fir; ++p1) if (sta1[p1].sec) pos1=p1;
for (; p2<top2&&!sta2[p2+1].fir; ++p2) if (sta2[p2].sec) pos2=p2;
if (pos1&&pos2) {
p1=pos1, p2=pos2;
decode1(sta1[p1].sec);
for (int i=1; i<=siz1; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
decode2(sta2[p2].sec);
for (int i=1; i<=siz2; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
printf("\n");
exit(0);
}
for (int p1=1,p2=top2; p1<=top1; ++p1) {
for (; p2>1&&sta1[p1].fir+sta2[p2].fir>p; --p2);
if (sta1[p1].fir+sta2[p2].fir==p) {
decode1(sta1[p1].sec);
for (int i=1; i<=siz1; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
decode2(sta2[p2].sec);
for (int i=1; i<=siz2; ++i) printf("%d ", tem[i]?(tem[i]==1?1:-1):0);
printf("\n");
exit(0);
}
}
puts("IMPOSSIBLE");
}
}
namespace task{
int top1, top2;
pair<ll, ll> sta1[N], sta2[N];
ll qcnt(ll l, ll r) {
// cout<<"qcnt: "<<l<<' '<<r<<endl;
ll ans=0;
for (int i=1,p1=top2,p2=top2; i<=top1; ++i) {
while (p1&&sta1[i].fir+sta2[p1].fir>=l) --p1;
while (p2&&sta1[i].fir+sta2[p2].fir>r) --p2;
ans+=p2-p1;
// cout<<"p: "<<p1<<' '<<p2<<endl;
}
// cout<<"now: "<<ans<<endl;
l+=p, r+=p;
// cout<<"lr: "<<l<<' '<<r<<endl;
for (int i=1,p1=top2,p2=top2; i<=top1; ++i) {
while (p1&&sta1[i].fir+sta2[p1].fir>=l) --p1;
while (p2&&sta1[i].fir+sta2[p2].fir>r) --p2;
ans+=p2-p1;
// cout<<"p: "<<p1<<' '<<p2<<endl;
}
// cout<<"return: "<<ans<<endl;
return ans;
}
void print(ll s, ll t) {
// ll val1=0, val2=0;
// for (int i=0; i<n; ++i) if (s&(1ll<<i)) val1+=a[i+1];
// for (int i=0; i<n; ++i) if (t&(1ll<<i)) val2+=a[i+1];
// assert(val1%p==val2%p);
ll mask=s&t;
s^=mask; t^=mask;
for (int i=0; i<n; ++i)
if (s&(1ll<<i)) printf("1 ");
else if (t&(1ll<<i)) printf("-1 ");
else printf("0 ");
printf("\n");
exit(0);
}
void solve() {
int siz1=n>>1, siz2=n-siz1;
int lim1=1<<siz1, lim2=1<<siz2;
for (int s=0; s<lim1; ++s) {
ll val=0;
for (int i=0; i<siz1; ++i) if (s&(1<<i))
val+=a[1+i];
sta1[++top1]={val%p, s};
}
for (int s=0; s<lim2; ++s) {
ll val=0;
for (int i=0; i<siz2; ++i) if (s&(1<<i))
val+=a[1+siz1+i];
sta2[++top2]={val%p, s};
}
sort(sta1+1, sta1+top1+1);
sort(sta2+1, sta2+top2+1);
// cout<<"sta1: "; for (int i=1; i<=top1; ++i) cout<<"("<<sta1[i].fir<<','<<sta1[i].sec<<") "; cout<<endl;
// cout<<"sta2: "; for (int i=1; i<=top2; ++i) cout<<"("<<sta2[i].fir<<','<<sta2[i].sec<<") "; cout<<endl;
ll l=0, r=p-1, mid;
while (l<r) {
// cout<<"lr: "<<l<<' '<<r<<' '<<qcnt(l, r)<<endl;
mid=(l+r+1)>>1;
// cout<<"val: "<<qcnt(mid, r)<<endl;
if (qcnt(mid, r)>r-mid+1) l=mid;
else r=mid-1;
}
mid=l;
// cout<<"mid: "<<mid<<endl;
// cout<<"cnt: "<<qcnt(510, 510)<<endl;
bool any=0; ll s;
for (int p1=1,p2=top2; p1<=top1; ++p1) {
for (; p2>1&&sta1[p1].fir+sta2[p2].fir>mid; --p2);
// if (sta1[p1].fir+sta2[p2].fir==mid) cout<<"1"<<endl;
for (int i=p2; i&&sta1[p1].fir+sta2[i].fir==mid; --i)
if (!any) any=1, s=(sta2[i].sec<<siz1)|sta1[p1].sec;
else print(s, (sta2[i].sec<<siz1)|sta1[p1].sec);
}
mid+=p;
for (int p1=1,p2=top2; p1<=top1; ++p1) {
for (; p2>1&&sta1[p1].fir+sta2[p2].fir>mid; --p2);
// if (sta1[p1].fir+sta2[p2].fir==mid) cout<<"1"<<endl;
for (int i=p2; i&&sta1[p1].fir+sta2[i].fir==mid; --i)
if (!any) any=1, s=(sta2[i].sec<<siz1)|sta1[p1].sec;
else print(s, (sta2[i].sec<<siz1)|sta1[p1].sec);
}
int cnt=0;
for (int i=1; i<=top1; ++i)
for (int j=1; j<=top2; ++j)
if (sta1[i].fir+sta2[i].sec==mid)
++cnt;
// cout<<"cnt: "<<cnt<<endl;
// cout<<qcnt(0, p-1)<<endl;
assert(0);
}
}
signed main()
{
n=read(); p=read();
for (int i=1; i<=n; ++i) a[i]=read();
// if (n<=20) force::solve();
// else task1::solve();
task::solve();
return 0;
}