Atcoder Beginner Contest 313
Atcoder Beginner Contest 313
从C开始,由G结束(Ex的插头DP实在有点。
C
给定数组
,每一次操作形如选择 , 。求使得最终 的最小操作次数。
数学题。
关注不变量,在本题中,数列
则可以得到方程:
因为
可以枚举
考虑到在最终局面下,原序列中所有比
D
这是一道交互题。
有一个长度为
的数组 ,其中 。 给定
,对于一次询问,给出 ,得到 的值。 要求进行不超过
次询问,确定 数组的值。
我们记
则容易发现
一个自然的想法是,我们依次询问
此时我们根据这
然后从 1 号点出发,作前缀异或和即可求出
但是,很遗憾,这是错的,并没有保证
But,这思想值得借鉴。试问只要我们能够建立出一颗关系树即可求得答案。但是如何避免这个环呢?
我们可以用
接着,我们如何得到
思想:不仅可以确定值,也可以从关系上考虑。
for(int i=1;i<=n;i++)a[i]=i;
for(int i=n+1;i<=n+n;++i)a[i]=a[i-n];
for(int i=k;i<=n;++i){
cout<<"? ";
for(int j=1;j<k;++j)cout<<j<<" ";cout<<i<<"\n";cout.flush();
int x;cin>>x;
if(i==k)s=x;
else add(k,i,(s!=x));
}
int lst=s;
for(int l=2;l<=k;++l){
int x=ask(l);
add(l-1,a[l+k-1],(x!=lst));
lst=x;
}
for(int i=1;i<=n;i++)if(!vis[i])dfs(i,0);
int cnt=0;
for(int i=1;i<=k;i++)if(!dis[i])++cnt;
cout<<"! ";
if(s==(cnt&1)){
for(int i=1;i<=n;i++)cout<<(dis[i]^1)<<" ";
}
else for(int i=1;i<=n;i++)cout<<dis[i]<<" ";
E
给定字符串
, ,定义 为:
- 新建一个字符串
,最初为空。 - 从
到 依次将 复制 次接在 后面。 定义一次操作为
,求经过多少次操作后 ,如果无解输出-1。
有意思的问题。我们先来考虑无解的情况。
什么时候无解?那必定是每一次操作都会扩大
故若有解,必然
现在我们来考虑计算操作数,由于从后面删,每删一个数又是一个同类子问题,考虑动态规划。
设
考虑当
当
在删掉
所以
发现两种情况下,递推式等价:
cin>>n;cin>>a+1;
for(int i=1;i<n;++i)
if(a[i]!='1'&&a[i+1]!='1'){
cout<<"-1\n";return 0;
}
for(int i=n;i>1;--i)ans=(a[i]-'0')*(ans+1)%p;
cout<<ans<<"\n"
F
有
张牌,每一张牌正面写上了数字 ,背面写上了数字 。最初所有牌都是正面朝上。 有
个机器,每个机器有参数 , 可以等于 。 每个机器只能启动一次,并且有
的概率将牌 翻转,同时有 的概率将牌 翻转。 你可以选择若干机器启动,使得最终局面中牌朝上的面的数字的期望和最大。求这个最大值。
有意思的期望问题。设选择的机器集合为
设
证明:
综上,
由此,我们可以得到一张牌是否被翻的概率与翻它的次数无关。
推论:每一次有
我们现在来考虑计算这个最大期望。显然,若翻了牌
设集合
设
Trick:抽离常数项,直接算
然后,我们考虑计算答案,记
先将牌分类,
对于一台机器
现在,我们来考虑计算贡献。
贪心地,我们要使得
这里用一个 启发式的思想
显然,贪心地,若选择了
,则与其相关的属于集合 的牌全部加入到 之中。 设
表示在所有机器中,与 共享同一台机器的属于集合 的牌的集合,现在我们枚举集合 根据贪心,
。 可以 预处理,枚举集合 的复杂度为 ,计算贡献的复杂度为 ,所以复杂度为 。
这时候也是一个关于子集的最优化问题。考虑使用动态规划求解。
这里的性质是什么呢?和上一个条件一样,若选择了
,则 中的所有数都应该被选择。 所以,我们设
表示在前 张属于 的牌中,选出属于集合 的牌的集合为 时,最小的代价和(这里的代价定义为从 中选出的牌的 值的和的相反数)。 容易得到:
DP复杂度为
。 然后考虑计算答案:我们枚举
,则 复杂度
。所以总复杂度
Trick:启发式分类处理.
在实现上,为了方便处理,可以先把所有的
#include<iostream>
#include<vector>
#include<cstring>
#define N 505050
#define int long long
using namespace std;
int a[N],b[N],x[N],y[N],id[N],fz[N],f[45][1<<21],ans;
vector<int>s,t;
signed main(){
ios::sync_with_stdio(false);int n,m;cin>>n>>m;
for(int i=0;i<n;i++)cin>>a[i]>>b[i];
for(int i=1;i<=m;i++)cin>>x[i]>>y[i],x[i]--,y[i]--;
for(int i=1;i<=m;i++)if(x[i]==y[i]&&a[x[i]]<b[y[i]])swap(a[x[i]],b[y[i]]);
for(int i=0;i<n;i++){
a[i]<<=1,b[i]<<=1;ans+=a[i];
if(a[i]>=b[i])id[i]=s.size(),s.push_back((a[i]-b[i])/2);
else id[i]=t.size(),t.push_back((b[i]-a[i])/2);
}
for(int i=1;i<=m;i++){
int l=x[i],r=y[i];
int f=(a[l]>=b[l]),g=(a[r]>=b[r]);
if(f==g&&f==0){
ans+=t[id[l]]+t[id[r]];
t[id[l]]=t[id[r]]=0;
}
else if(f!=g){
if(!f)swap(l,r);
fz[id[l]]|=(1ll<<id[r]);
}
}
int cs=s.size(),ct=t.size(),mx=0;
if(cs<=ct){//\sum t-s
for(int i=0;i<(1ll<<cs);++i){
int w=0,c=0;
for(int j=0;j<cs;++j){
if((i>>j)&1)w-=s[j],c|=fz[j];
}
for(int j=0;j<ct;++j)if((c>>j)&1)w+=t[j];
mx=max(mx,w);
}
}
else {
memset(f,-0x3f,sizeof f);
f[0][0]=0;
for(int i=0;i<cs;++i){
for(int j=0;j<(1ll<<ct);++j){
f[i+1][j]=max(f[i+1][j],f[i][j]);
f[i+1][j|fz[i]]=max(f[i+1][j|fz[i]],f[i][j]-s[i]);
}
}
for(int i=0;i<(1<<ct);++i){
int w=f[cs][i];
for(int j=0;j<ct;++j)if((i>>j)&1)w+=t[j];
mx=max(mx,w);
}
}
ans+=mx;
if(ans&1)cout<<ans/2<<".500000\n";
else cout<<ans/2<<".000000\n";
}
G
有
堆石子,石子数相异,每次操作分为以下两种:
- 从每一个还有石子的堆中各取出一个放入背包。
- 从背包中取出
个石子放入每一堆中。 可以进行无限次操作,求可能形成的局面个数。(对
取模)
ABC313简直了。
显然对于一个局面来说,操作顺序没有影响,我们只需要考虑两种操作分别进行的次数即可。
不妨假设先全部进行操作1,再全部进行操作2。
显然,清空的堆数不同,局面数必定不同。(清空
设
设前缀和数组
则:
对于这个式子的计算?看类欧几里得算法简单形式
特别地,
答案为
int f(int a,int b,int c,int n){
if(n<0)return 0;
int w=0;
if(a>=c)w+=n*(n+1)*(a/c)/2,a%=c,w%=p;
if(b>=c)w+=(n+1)*(b/c),b%=c,w%=p;
int m=(a*n+b)/c;
w+=n*m%p-f(c,c-b-1,a,m-1)%p;w%=p;
return w;
}
signed main(){
read(n);for(int i=1;i<=n;i++)read(a[i]);
sort(a+1,a+n+1);s=0;int ans=0;
for(int i=1;i<n;i++){
s+=a[i];
ans=(ans+f(n-i,s+i,n,a[i+1])-f(n-i,s+i,n,a[i]))%p;
ans=(ans%p+p)%p;
}
s+=a[n];ans+=s/n+1;
cout<<(ans%p+p)%p<<"\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!