「AGC022C」 Remainder Game

题意

\(n\) 个整数 \(a_i\),可以对它们进行若干次操作:每次可以选择一个整数 \(k\) 和数组中的一些数,花费 \(2^k\) 的代价,给这些数赋值为原值对 \(k\) 取模的值。

求出最小的花费,使得数组 \(a\) 变成数组 \(b\),如果不存在这种方案,输出 \(-1\)

分析

注意到题目里的 \(n,k\) 范围都很小,并且每次操作的代价都是 \(2\) 的次幂,所以可以按位考虑。

如果选择一个数 \(k\),那么选它的代价比选择 \(1\sim k-1\) 的代价和都要大,所以从大到小枚举 \(k\),写一个 check 判断这个数是不是必须选取。

给每一个位置开一个 bool 数组,记录当前位置是否可以变成一个数,每次初始给 \(vis_{i,a_i}\) 赋值为 \(1\)

然后再枚举一遍 \(k,n\),枚举可能产生的值,把它们对应的位置赋为 \(1\),具体可以看代码。

最后看看第 \(i\) 位能不能变成 \(b_i\) 就可以了,注意开始的时候判断一下有没有解。

代码里用了 bitset,还能给时间复杂度除个 \(w\)

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define dbg(x) cout<<#x<<": "<<x<<"\n"
static char buf[100],*p1=buf,*p2=buf,obuf[100],*p3=obuf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,100,stdin),p1==p2)?EOF:*p1++
#define putchar(x) (p3-obuf<100)?(*p3++=x):(fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=x)
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
inline void write(ll x){if(!x){putchar(48);putchar('\n');return;}short top=0,s[40];if(x<0)x=-x,putchar(45);while(x)s[top++]=x%10^48,x/=10;while(top--)putchar(s[top]);putchar('\n');}
mt19937_64 rnd(chrono::system_clock::now().time_since_epoch().count());
const ll mod=998244353,maxn=55,maxt=505;
ll n,a[maxn],b[maxn],f[maxn];
bitset<maxn>vis[maxn];
inline bool chk(){
    for(ll i=1;i<=n;++i)vis[i].reset();
    for(ll i=1;i<=n;++i)vis[i][a[i]]=1;
    for(ll i=51;i>=1;--i){
        if(!f[i])continue;
        for(ll j=1;j<=n;++j){
            for(ll k=a[j];k>=i;--k){
                vis[j][k%i]=vis[j][k%i]|vis[j][k];
            }
        }
    }
    for(ll i=1;i<=n;++i)if(!vis[i][b[i]])return 0;
    return 1;
}
inline void solve(){
    n=read();
    for(ll i=1;i<=n;++i)a[i]=read();
    for(ll i=1;i<=n;++i)b[i]=read();
    for(ll i=1;i<=51;++i)f[i]=1;
    if(!chk())return write(-1),void();
    ll ans=0;
    for(ll i=51;i>=1;--i){
        f[i]=0;
        if(!chk())f[i]=1,ans+=(1ll<<i);
    }
    write(ans);
}
signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ll t=1;
    while(t--){
        solve();
    }
    fwrite(obuf,p3-obuf,1,stdout);
    return 0;
}
posted @ 2024-12-20 15:28  run-away  阅读(16)  评论(0)    收藏  举报