CF505
CF505A
注意到 \(|s|<=10\),那么暴力枚举每个字母和插入位置即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define gc getchar
#define pc putchar
const int N=5e4+5;
const int M=2e7+5;
const int inf=0x7fffffff;
const int mod=1e6+3;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m;
string s,t,k;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>s;
for(int i=0;i<=s.size();i++){
for(int j=1;j<=26;j++){
t=s;k=(char)('a'+j-1);
t.insert(i,k);int flag=1;
for(int l=0,r=t.size()-1;l<r;l++,r--)flag&=t[l]==t[r];
if(flag){
cout<<t<<endl;
return 0;
}
}
}
puts("NA");
return 0;
}
CF505B
\(n,m,q\leq 100\) 那么 \(O(n^3m)\) 暴力 floyd 即可
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define gc getchar
#define pc putchar
const int N=1e2+5;
const int M=2e7+5;
const int inf=0x7fffffff;
const int mod=1e6+3;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,dis[N][N][N];
signed main(){
n=read();m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),c=read();
dis[u][v][c]=dis[v][u][c]=1;
}
for(int c=1;c<=m;c++){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dis[i][j][c]|=dis[i][k][c]&dis[k][j][c];
}
}
}
}
int q=read();
while(q--){
int u=read(),v=read(),ans=0;
for(int i=1;i<=m;i++)ans+=dis[u][v][i];
writel(ans);
}
return 0;
}
CF505C
发现贪心不可行,那么考虑dp。
一个显然的状态:设 \(f_{i,j}\) 表示到 \(i\) 位置,上一次走 \(j\) 步的最大答案 转移显然
然鹅 \(n,m\leq 30000\) 空间、时间都炸了
发现每次步数只会+1或-1 发现步数最大只会变400次
那么改下状态:设 \(f_{i,j}\) 表示到 \(i\) 位置,上一次教开始的 \(d\) 变化了 \(j-M\) 的最大答案
(M=400 整体右移 防止出现负数)
复杂度 \(O(800n)\)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define gc getchar
#define pc putchar
const int N=3e4+5;
const int M=4e2+5;
const int inf=0x7fffffff;
const int mod=1e6+3;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,d,num[N],f[N][(M<<1)+5],p[N],ans;
signed main(){
n=read(),d=read();
for(int i=1;i<=n;i++){
p[i]=read();
num[p[i]]++;
}
memset(f,-1,sizeof f);
f[d][M]=num[0]+num[d];
for(int i=d;i<=p[n];i++){
for(int j=-M;j<=M;j++){
if(!~f[i][j+M])continue;
for(int z=-1;z<=1;z++){
int len=j+d+z;
if(len<1||i+len>p[n]||j+z+M<0||j+z+M>(M<<1))continue;
f[i+len][j+M+z]=max(f[i+len][j+M+z],f[i][j+M]+num[i+len]);
}
ans=max(ans,f[i][j+M]);
}
}
writel(ans);
return 0;
}
CF505D
发现如下性质:
- 当该联通块为DAG时 一定可以用一条链连起来 且满足题意
- 当联通块中有环时 就把所有点串成环 两点之间必然可达
两种情况答案分别为 \(cnt-1\)、\(cnt\)
(\(cnt\) 为联通块大小)
可以通过拓扑排序判环 存在一个点入度总大于0则有环
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define gc getchar
#define pc putchar
const int N=1e5+5;
const int M=4e2+5;
const int inf=0x7fffffff;
const int mod=1e6+3;
inl int read(){
int x=0,f=1;char c=gc();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return x*f;
}
inl void write(int x){
if(x<0){pc('-');x=-x;}
if(x>9)write(x/10);
pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,fa[N],in[N],ans,q[N],h,t=1,inq[N],res[N];
int head[N],nxt[N],to[N],cnt;
inl void add(int u,int v){
nxt[++cnt]=head[u];
to[cnt]=v;
head[u]=cnt;
}
inl int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
signed main(){
n=ans=read(),m=read();
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int u=read(),v=read();
add(u,v);
in[v]++;
int fu=find(u),fv=find(v);
if(fu==fv)continue;
fa[fu]=fv;
}
for(int i=1;i<=n;i++){
if(!in[i])q[++h]=i,inq[i]=1;
}
while(h>=t){
int x=q[t++];
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(!--in[y])q[++h]=y,inq[y]=1;
}
}
for(int i=1;i<=n;i++){
if(!inq[i])res[find(i)]=1;
}
for(int i=1;i<=n;i++){
if(i^find(i))continue;
ans-=!res[i];
}
writel(ans);
return 0;
}