Codeforces Round 976 (Div. 2) 题解(A-E)
Codeforces Round 976(Div 2) 题解 (A-E)
A
题意
给你两个整数 \(n\) 和 \(k\) 。
在一次操作中,你可以从 \(n\) 中减去 \(k\) 的任意次幂。形式上,在一个操作中,你可以用 \((n-k^x)\) 替换任何非负整数 \(x\) 的 \(n\) 。
求使 \(n\) 等于 \(0\) 所需的最小运算次数。
Solution
将 \(n\) 转为 \(k\) 进制,答案即为每位的数的和。时间复杂度 \(O(\sum logn)\) 。
#include <bits/stdc++.h>
#define LL long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
void write(LL x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+48);
}
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
const int N=60;
int n,k,a[N],cnt;
void solve(){
n=read(),k=read(),cnt=0;
if(k==1){
write(n),puts("");
return;
}
while(n){
a[++cnt]=n%k;
n/=k;
}
LL ans=0;
for(int i=1;i<=cnt;++i){
ans+=a[i];
}
write(ans),puts("");
}
int main(){
int T=read();
while(T--){
solve();
}
return 0;
}
B
题意
假设你有编号为 \(1, 2, \ldots, n\) 的 \(n\) 灯泡。最初,所有的灯泡都是亮着的。翻转灯泡的状态意味着如果它以前是开着的,就把它关掉,否则就把它打开。
接下来,执行以下操作:
- 对于每个 \(i = 1, 2, \ldots, n\) ,翻转所有 \(j\) 的灯泡状态,使 \(j\) 能被 \(i^\dagger\) 整除。
在完成所有操作后,将有几个灯泡仍然亮着。您的目标是使这个数字恰好为 \(k\) 。
找到最小的合适的 \(n\) ,使得在执行操作后恰好有 \(k\) 个灯泡亮着。我们可以证明一个答案总是存在的。
\(^\dagger\) 一个整数 \(x\) 能被 \(y\) 整除,如果存在一个整数 \(z\) 能被 \(x = y\cdot z\) 整除。
Solution
第 \(i\) 个灯会被操作 \(i\) 的因数个数次。第 \(i\) 个灯操作之后仍是亮着的,当且仅当 \(i\) 是完全平方数。二分即可。
时间复杂度 \(O(TlogV)\) 。
#include <bits/stdc++.h>
#define LL long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
void write(LL x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+48);
}
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
LL k;
void solve(){
k=read();
LL L=2,R=2e18,res;
auto chk=[&](LL x)->bool{
return x-(LL)sqrtl(x)>=k;
};
while(L<=R){
LL mid=L+R>>1;
if(chk(mid)) R=mid-1,res=mid;
else L=mid+1;
}
write(res),puts("");
}
int main(){
int T=read();
while(T--) solve();
return 0;
}
C
题意
给定三个非负整数 \(b\) , \(c\) 和 \(d\) 。
请找到一个非负整数 \(a \in [0, 2^{61}]\) ,使得 \((a | b)-(a \& c)=d\) ,其中 \(|\) 和 \(\&\) 分别表示位或操作和位与操作。
如果存在 \(a\) ,则打印其值。如果没有解,则打印单个整数 \(-1\) 。如果有多个解决方案,打印其中任何一个。
Solution
将 \(a,b,c\) 转为二进制,分类讨论每一位上的情况。时间复杂度 \(O(TlogV)\) 。
#include <bits/stdc++.h>
#define LL long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
void write(LL x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+48);
}
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
const int N=65;
LL a;
void solve(){
LL x=read(),y=read(),z=read();
auto cal=[&](LL x)->vector<int>{
vector<int> ans(N);
int cnt=0;
while(x){
ans[++cnt]=x%2;
x>>=1;
}
return ans;
};
vector<int> b=cal(x);
vector<int> c=cal(y);
vector<int> d=cal(z);
for(int i=64;i>=1;--i){
LL opt;
if(d[i]==0){
if(b[i]==0 && c[i]==0) opt=0;
else if(b[i]==1 && c[i]==1) opt=1;
else if(b[i]==0 && c[i]==1) opt=0;
else{
puts("-1");
return;
}
}
else{
if(b[i]==0 && c[i]==0) opt=1;
else if(b[i]==1 && c[i]==1) opt=0;
else if(b[i]==1 && c[i]==0) opt=1;
else{
puts("-1");
return;
}
}
a=(a<<1)+opt;
}
write(a),puts("");
}
int main(){
int T=read();
while(T--) solve();
return 0;
}
D
题意
一个晴朗的晚上,爱丽丝坐下来玩经典的游戏“串连点”,但有一个转折。
为了玩这个游戏,爱丽丝画了一条直线,并在上面标记了 \(n\) 点,索引从 \(1\) 到 \(n\) 。最初,点之间没有弧,所以它们都是不相交的。之后,Alice执行如下类型的 \(m\) 操作:
- 她选择了三个整数 \(a_i\) , \(d_ i\) ( \(1 \le d _ i \le 10\) )和 \(k _ i\) 。
- 她选择点 \(a _ i, a _ i+d _ i, a _ {i}+2d_ i, a _ i+3d _ i, \ldots, a _ i+k _ i\cdot d _ i\) 并将这些点的每一对用弧连接起来。
在完成所有 \(m\) 操作后,她想知道这些点形成的 \(\dagger\) 连接组件的个数。请帮她找到这个号码。
\(\dagger\) 如果两点之间有一条通过若干(可能为零)弧线和其他点的路径,则称两点在一个连通分量中。
Solution
注意到 \(d_i\) 很小,因此对于一个点,它只可能被它前面的 \(10\) 个点内的点连接,用并查集维护。时间复杂度 \(O(\sum nlogn)\) 。
#include <bits/stdc++.h>
#define LL long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
void write(LL x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+48);
}
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
const int N=2e5+5;
int n,m,a,d,p,cnt[N][11],fa[N];
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void solve(){
n=read(),m=read();
for(int i=1;i<=n;++i){
fa[i]=i;
}
for(int i=1;i<=m;++i){
a=read(),d=read(),p=read();
cnt[a][d]=max(cnt[a][d],p);
}
auto merge=[&](int x,int y)->void{
x=find(x),y=find(y);
if(x==y) return;
fa[x]=y;
};
for(int i=1;i<=n;++i){
for(int j=max(1,i-10);j<i;++j){
int k=i-j;
if(!cnt[j][k]) continue;
cnt[i][k]=max(cnt[i][k],cnt[j][k]-1);
merge(i,j);
}
}
int ans=0;
for(int i=1;i<=n;++i){
if(find(i)==i) ans++;
}
write(ans),puts("");
for(int i=1;i<=n;++i){
for(int j=1;j<=10;++j){
cnt[i][j]=0;
}
}
}
int main(){
int T=read();
while(T--) solve();
return 0;
}
E
Solution
考虑 \(dp_{i,j}\) 表示前 \(i\) 个数能构成的集合且其中元素的异或和为 \(j\) 能发生的概率。
答案为
时间复杂度 \(O(\sum 1024n)\) 。
小心写得不好导致爆long long;多测记得清空。
#include <bits/stdc++.h>
#define LL long long
#define mod 1000000007
#define lowbit(x) (x&(-x))
void write(LL x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+48);
}
LL read(){
LL x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
using namespace std;
const int N=2e5+5;
LL n,a[N],p[N],inv,dp[2][1050];
LL qpow(LL x,LL power){
LL ans=1;
x%=mod;
while(power){
if(power&1) ans=ans*x%mod;
power>>=1;
x=x*x%mod;
}
return ans;
}
void solve(){
n=read();
for(int i=1;i<=n;++i){
a[i]=read();
}
inv=qpow(10000,mod-2);
for(int i=1;i<=n;++i){
p[i]=read()*inv%mod;
}
memset(dp,0,sizeof(dp));
dp[1][a[1]]=p[1];
dp[1][0]=(1-p[1]+mod)%mod;
for(int i=1;i<n;++i){
for(int j=0;j<1024;++j){
dp[(i+1)&1][j^a[i+1]]=(dp[(i+1)&1][j^a[i+1]]+1ll*dp[i&1][j]*p[i+1]%mod)%mod;
dp[(i+1)&1][j]=(dp[(i+1)&1][j]+1ll*dp[i&1][j]*(1-p[i+1]+mod)%mod)%mod;
}
for(int j=0;j<1024;++j) dp[i&1][j]=0;
}
LL ans=0;
for(int i=0;i<1024;++i){
ans=(ans+1ll*dp[n&1][i]*i%mod*i%mod)%mod;
}
write(ans),puts("");
}
int main(){
int T=read();
while(T--) solve();
return 0;
}

浙公网安备 33010602011771号