A.
想让“三个元素互不相同”,直接把 a1 放到 a3 之后。
void solve(){
ll a1,a2,a3;cin>>a1>>a2>>a3;
cout<<a2<<" "<<a3<<" "<<a1<<endl;
}
B.
回文串是指一个字符串,其正读和反读都一样。例如,"level" 和 "noon" 都是回文串。
题目要求”所有字符都互不相同“,很明显只有 n=1 的时候可以构造一个单字符的回文串,也就是说随便输出一个小写字母,其他情况一律 No。
void solve(){
int n;cin>>n;
if(n==1){
cout<<"a"<<endl;
}else{
cout<<"No"<<endl;
}
}
C.
先算 1..n 里奇数个数和偶数个数,再看字符串里强制奇位(j)、强制偶位(o)、自由位(?)各有多少。
如果强制需求已经超了就直接 0;否则从 ? 里挑一些补奇位,剩下补偶位,方案数是组合数 C(?,补奇)。
最后奇数们在奇位内部还能全排列、偶数们在偶位内部也能全排列,所以再乘 odd! 和 even!。
void solve(){
int n;cin>>n;
string s;cin>>s;
int o=(n+1)/2,e=n/2;
int cj=0,co=0,cq=0;
for(int i=0;i<n;++i){
if(s[i]=='j')++cj;
else if(s[i]=='o')++co;
else ++cq;
}
int ro=o-cj,re=e-co;
if(ro<0||re<0||ro+re!=cq){
cout<<0<<endl;
return;
}
vll fac(n+1,1),ifac(n+1,1);
for(int i=1;i<=n;++i)fac[i]=fac[i-1]*i%MOD2;
ifac[n]=qpow(fac[n],MOD2-2,MOD2);
for(int i=n;i>=1;--i)ifac[i-1]=ifac[i]*i%MOD2;
auto C=[&](int N,int K)->ll{
if(K<0||K>N)return 0;
return fac[N]*ifac[K]%MOD2*ifac[N-K]%MOD2;
};
ll ans=C(cq,ro)*fac[o]%MOD2*fac[e]%MOD2;
cout<<ans%MOD2<<endl;
}
D.
先找原数组中位数 x,然后把数分成 <x、=x、>x 三类,问题变成“删最少元素让新中位数不再是 x”。
等价做法是反过来想:最多能保留多少元素且中位数变小(或变大),两种方向各算一次取最大保留。
答案就是 n-最大可保留;如果两边都做不到,就输出 -1。
void solve(){
int n;cin>>n;
vll a(n+1);
for(int i=1;i<=n;++i)cin>>a[i];
vll c;
c.reserve(n);
for(int i=1;i<=n;++i)c.push_back(a[i]);
sort(all(c));
ll x=c[(n-1)/2];
int l=0,e=0,g=0;
for(int i=1;i<=n;++i){
if(a[i]<x)++l;
else if(a[i]==x)++e;
else ++g;
}
int m1=0,m2=0;
if(l>0)m1=l+min(e+g,l);
if(g>0)m2=g+min(l+e,g-1);
int m=max(m1,m2);
if(m==0){
cout<<-1<<endl;
return;
}
cout<<n-m<<endl;
}
E.
把这当成博弈 DP:小红每回合走一步,小紫随后会删掉小红相邻的一个红点来“卡她后路”。
对非根节点 u,若它有至少两个“对红方有利”的子方向(能直接到叶子或继续形成必胜),那红方在 u 才能稳住优势。
最后看根节点 1 是否存在一个能让红方开局占优的相邻点,有就 red,没有就 purple。
void solve(){
int n;cin>>n;
vvi g(n+1);
for(int i=1;i<=n-1;++i){
int u,v;cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
vi fa(n+1,0),ord;
ord.reserve(n);
vi st;
st.push_back(1);
fa[1]=-1;
while(!st.empty()){
int u=st.back();
st.pop_back();
ord.push_back(u);
for(int v:g[u]){
if(v==fa[u])continue;
fa[v]=u;
st.push_back(v);
}
}
vi ch(n+1,0),win(n+1,0),isL(n+1,0);
for(int u=2;u<=n;++u){
++ch[fa[u]];
}
for(int u=1;u<=n;++u){
if(ch[u]==0)isL[u]=1;
}
for(int i=n-1;i>=0;--i){
int u=ord[i];
if(u==1)continue;
int c=0;
for(int v:g[u]){
if(v==fa[u])continue;
if(isL[v]||win[v])++c;
}
win[u]=(c>=2);
}
int ok=0;
for(int v:g[1]){
if(isL[v]||win[v]){
ok=1;
break;
}
}
if(ok)cout<<"red"<<endl;
else cout<<"purple"<<endl;
}
F.
先用一条长度 m 的链凑出 m-1 对相邻点,这是最稳定、最好控的基本块。
不够的话再拼网格/加一小段“贴边扩展”来批量增加相邻对,最后剩下的点全丢到很远的位置避免产生新相邻。
如果目标 k 超过 n 个点能达到的上限(大致是平面格点图的极限边数),就无解输出 No;否则输出构造点集。
void solve(){
ll n,k;cin>>n>>k;
if(k==0){
cout<<"Yes"<<endl;
cout<<0<<" "<<0<<endl;
for(ll i=2;i<=n;++i){
cout<<-1000000000+3*i<<" "<<-1000000000<<endl;
}
return;
}
ll bp=LINF,bh=-1,bw=-1,bx=-1,br=-1,typ=0;
if(k+1<=n){
bp=k+1;
typ=1;
}
ll hlim=min<ll>(n,1000);
for(ll h=1;h<=hlim;++h){
ll est=(k+h)/(2*h-1);
for(ll dw=-3;dw<=3;++dw){
ll w=est+dw;
if(w<=0)continue;
ll m0=h*w;
if(m0>n)continue;
ll e0=2*h*w-h-w;
if(e0>k)continue;
ll rem=k-e0;
ll x=0;
if(rem>0)x=min<ll>(w,(rem+1)/2);
ll e=e0+(x?2*x-1:0);
ll r=k-e;
ll p=m0+x+(r?r+1:0);
if(p<bp){
bp=p;
bh=h;bw=w;bx=x;br=r;
typ=2;
}
}
}
if(bp>n){
cout<<"No"<<endl;
return;
}
cout<<"Yes"<<endl;
vpll ans;
ans.reserve(n);
if(typ==1){
for(ll i=0;i<=k;++i){
ans.push_back({i,0});
}
}else{
for(ll y=0;y<bh;++y){
for(ll x=0;x<bw;++x){
ans.push_back({x,y});
}
}
for(ll x=0;x<bx;++x){
ans.push_back({x,bh});
}
if(br>0){
ll sx=500000000,sy=500000000;
for(ll i=0;i<=br;++i){
ans.push_back({sx+i,sy});
}
}
}
for(ll i=(ll)ans.size();i<n;++i){
ans.push_back({-1000000000+3*i,-1000000000});
}
for(auto &p:ans){
cout<<p.fi<<" "<<p.se<<endl;
}
}

京公网安备 11010502036488号