ABC313
D - Odd or Even
假设
#include <bits/stdc++.h>
using namespace std;
const int maxn=2005;
int n,k,a[maxn],tval[maxn];
int query(vector<int> S)
{
printf("? ");
for(int v:S)printf("%d ",v);
putchar('\n');
fflush(stdout);
int x;scanf("%d",&x);
return x;
}
int tx=0;
int main()
{
scanf("%d%d",&n,&k);
if(k==1)
{
vector<int> now;
for(int i=1;i<=n;i++){now.clear();now.push_back(i);tval[i]=query(now);}
printf("! ");for(int i=1;i<=n;i++)printf("%d ",tval[i]);putchar('\n');
return 0;
}
vector<int> tS;
for(int i=1;i<k;i++)tS.push_back(i);
for(int i=k;i<=n;i++)
{
tS.push_back(i);
tval[i]=query(tS);
//printf("%d %d\n",i,tval[i]);
tS.pop_back();
}
int bp=tval[k]^tval[k+1];
for(int i=k-1;i>=1;i--)
{
tS.clear();
tS.push_back(k);tS.push_back(k+1);
for(int j=1;j<k;j++)if(i!=j)tS.push_back(j);
int x=query(tS);
tval[i]=bp^x;
//printf("%d %d",i,tval[i]);putchar('\n');
}
bp=0;
int x=1;
for(int i=2;i<k;i++)bp^=tval[i];
if(bp!=tval[1])for(int i=1;i<=n;i++)tval[i]^=1;
printf("! ");
for(int i=1;i<=n;i++)printf("%d ",tval[i]);
putchar('\n');
fflush(stdout);
return 0;
}
E - Duplicate
考虑什么时候删不成
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10,mod=998244353;
int n;
char s[maxn];
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
cin>>s+1;
int now=1;
for(int i=1;i<n;i++)
if(s[i]!='1'&&s[i+1]!='1')
{
puts("-1");
return 0;
}
int nowt=1;
for(int i=n-1;i>=1;i--)
{
int x=s[i+1]-'0';
nowt=(1ll*nowt+1+1ll*(x-1)*nowt%mod)%mod;
}
cout<<nowt-1<<endl;
return 0;
}
F - Flip Machines
我们并不关心一个牌可能会被翻几次,只有最后一次和它相关的翻转决定它是正还是反。(注意因为这点你要特判
令
这样dp的复杂度降低到了
#include <bits/stdc++.h>
using namespace std;
const int maxn=44;
int n,m,X[100005],Y[100005];
double dp[maxn][(1<<21)];
double a[maxn],b[maxn],d[maxn];
int tp[maxn],idp[maxn],plen,tq[maxn],idq[maxn],qlen;
vector<int> G[maxn];
bool tag[maxn],pnt[maxn];
int main()
{
// freopen("data.in","r",stdin);
// freopen("1.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i],d[i]=abs(a[i]-b[i])/2;
for(int i=1;i<=m;i++)
cin>>X[i]>>Y[i],G[X[i]].push_back(Y[i]),G[Y[i]].push_back(X[i]);
for(int i=1;i<=m;i++)
if(X[i]==Y[i]&&a[X[i]]<b[X[i]])swap(a[X[i]],b[X[i]]);
for(int i=1;i<=n;i++)
if(a[i]>=b[i])tp[idp[i]=plen++]=i,pnt[i]=0;
else tq[idq[i]=qlen++]=i,pnt[i]=1;
//printf("%d %d\n",plen,qlen);
for(int i=1;i<=m;i++)
if(pnt[X[i]]==1&&pnt[Y[i]]==1)tag[X[i]]=tag[Y[i]]=1;
if(plen<qlen)
{
//puts("!");
for(int j=0;j<=plen;j++)for(int i=0;i<(1<<plen);i++)dp[j][i]=-1e18;
dp[0][0]=0;
for(int i=0;i<qlen;i++)
{
int u=tq[i];
for(int S=0;S<(1<<plen);S++)
{
if(dp[i][S]==-1e18)continue;
dp[i+1][S]=max(dp[i+1][S],dp[i][S]+(tag[u]?d[u]:0));
for(int v:G[u])
dp[i+1][S|(1<<idp[v])]=max(dp[i+1][S|(1<<idp[v])],dp[i][S]+d[u]);
}
}
double ans=-1e18,sum=0;
for(int i=1;i<=n;i++)sum+=a[i];
for(int i=0;i<(1<<plen);i++)
if(dp[qlen][i]==-1e18)continue;
else
{
double now=dp[qlen][i];
for(int j=0;j<plen;j++)if((i>>j)&1)now-=d[tp[j]];
ans=max(ans,now+sum);
}
cout<<fixed<<setprecision(6)<<ans<<endl;
}
else
{
//puts("@");
for(int j=0;j<=plen;j++)for(int i=0;i<(1<<qlen);i++)dp[j][i]=-1e18;
dp[0][0]=0;
for(int i=0;i<plen;i++)
{
int u=tp[i];
for(int S=0;S<(1<<qlen);S++)
{
if(dp[i][S]==-1e18)continue;
dp[i+1][S]=max(dp[i+1][S],dp[i][S]);
int T=0;
for(int v:G[u])
if(pnt[v])T|=(1<<idq[v]);
dp[i+1][S|T]=max(dp[i+1][S|T],dp[i][S]-d[u]);
}
}
double ans=-1e18,sum=0;
for(int i=1;i<=n;i++)sum+=a[i];
for(int i=0;i<(1<<qlen);i++)
if(dp[plen][i]==-1e18)continue;
else
{
double now=dp[plen][i];
for(int j=0;j<qlen;j++)if(((i>>j)&1)||(tag[tq[j]]))now+=d[tq[j]];
ans=max(ans,now+sum);
}
cout<<fixed<<setprecision(6)<<ans<<endl;
}
}
G - Redistribution of Piles
为了不重不漏的计数,考虑枚举所有可能的相对大小。
一点一点的往下减,发现如果出现了
#include <bits/stdc++.h>
#include <atcoder/all>
#define int long long
using namespace atcoder;
using namespace std;
const int maxn=2e5+10,mod=998244353;
int a[maxn],n;
pair<int,int> p[maxn];
signed main()
{
ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],p[i]={a[i],i};
sort(p+1,p+1+n);
int nowsum=p[1].first*n,nowbot=p[1].first,ans=p[1].first+1;
for(int i=2;i<=n;i++)
{
int lim=p[i].first-nowbot;
if(lim==0)continue;
int val=floor_sum(lim,n,n-i+1,n-i+1+nowsum+n)%mod;
//cout<<val<<endl;
ans=(ans+val)%mod;
nowsum+=1ll*(p[i].first-nowbot)*(n-i+1);
nowbot=p[i].first;
}
ans%=mod;
cout<<ans<<endl;
}
Ex - Group Photo
我们先将
我们从小到大依次加入
夹在两个放过的数之间,那 不会出现,系数为 ,转移到 。 在一个放过的数左边或右边,那 出现一次,系数为 ,转移到 。 不与之前放的数相邻,那 出现两次。系数为 (排列dp只考虑相对关系),转移到 。
答案就是
#include <bits/stdc++.h>
using namespace std;
const int maxn=5005,mod=998244353;
int n,a[maxn],b[maxn],dp[maxn][maxn];
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n+1;i++)cin>>b[i];
sort(a+1,a+1+n);
sort(b+1,b+1+n+1);
dp[0][0]=1;
for(int i=0;i<n;i++)
for(int j=0;j<=i;j++)
{
if(!dp[i][j])continue;
if(j>=2&&i+j<=n+1)dp[i+1][j-1]=(dp[i+1][j-1]+1ll*dp[i][j]*(j-1)%mod)%mod;
if(j>=1&&i+j+1<=n+1&&a[i+1]<b[i+j+1])dp[i+1][j]=(dp[i+1][j]+1ll*dp[i][j]*2%mod*j%mod)%mod;
if(i+j+2<=n+1&&a[i+1]<b[i+j+1]&&a[i+1]<b[i+j+2])dp[i+1][j+1]=(dp[i+1][j+1]+1ll*dp[i][j]*(j+1)%mod)%mod;
}
cout<<dp[n][1]<<endl;
}
本文作者:_kkio
本文链接:https://www.cnblogs.com/hikkio/p/17609673.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!