AtCoder Beginner Contest 244
题意:交互题。题意很简单,数据范围也很小,直接暴力做就行。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=1e5+10;
bool st[N];
void work()
{
int n; cin>>n;
cout<<1<<endl;
st[1]=1;
for(int i=1;i<=n+1;i++){
int x; cin>>x;
if(!x) return ;
st[x]=1;
for(int i=1;i<=n*2+1;i++){
if(!st[i]) {
cout<<i<<endl;
st[i]=1;
break;
}
}
}
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
}
题意:给定长度为3的字符串, s , t s,t s,t,是 R G B RGB RGB的一个排列,问能否经过 1 0 18 10^{18} 1018次交换,使s变为t。
通过模拟几组样例可得,当其所有位置完全相等或完全不等时,可以转换。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=1e5+10;
bool st[N];
void work()
{
string s,t;
int sum=0;
for(int i=0;i<3;i++){
cin>>s[i];
}
for(int i=0;i<3;i++){
cin>>t[i];
}
for(int i=0;i<3;i++){
if(s[i]!=t[i]) sum++;
}
cout<<s<<" "<<t<<endl;
if(sum==0||sum==3) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
}
题意:给定一张无向图,给定起点s, 终点t, 问有多少个序列满足如下条件:
- 长度为 k + 1 k+1 k+1.
- A 0 = s , A k = t A_0=s,A_k=t A0=s,Ak=t.
- A i 到 A i + 1 A_i到A_{i+1} Ai到Ai+1有一条边直接相连。
- x 在序列 A 中出现偶数次 x在序列A中出现偶数次 x在序列A中出现偶数次。
对于这种计数类的问题,可以考虑用dp来求解,关键是怎么表示状态。可以定义 d p [ i ] [ j ] 表示当前选了 i 条边,当前在点 j 的方案数 dp[i][j]表示当前选了i条边,当前在点j的方案数 dp[i][j]表示当前选了i条边,当前在点j的方案数。
如果不考虑第四个条件,那么答案就是 d p [ k ] [ t ] dp[k][t] dp[k][t],那考虑条件4呢?我们可以把状态增加一维,0表示经过偶数次,1表示经过奇数次。
那最终答案为 d p [ k ] [ t ] [ 0 ] dp[k][t][0] dp[k][t][0].
由于所给的图是无向图,因此状态转移时要对两个方向转移。而且在状态转移时,无需把图建出来,只需记录边,然后转移即可。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=2e3+10,mod=998244353;
bool st[N];
pii e[N];
int dp[N][N][2];//f[i][j][0]从起点到j,用了i条边,经过x偶数次方案数
//f[i][j][1]从起点到j,用了i条边,经过x奇数次方案数
void work()
{
int n,m,k,s,t,x;
cin>>n>>m>>k>>s>>t>>x;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
e[i]={a,b};
}
dp[0][s][0]=1;
for(int i=1;i<=k;i++){
for(int j=1;j<=m;j++){
int u=e[j].x,v=e[j].y;
//cout<<u<<"##"<<v<<endl;
for(int c=0;c<2;c++){
if(u==x) dp[i][u][c]=(dp[i-1][v][c^1]+dp[i][u][c])%mod;
else dp[i][u][c]=(dp[i-1][v][c]+dp[i][u][c])%mod;
if(v==x) dp[i][v][c]=(dp[i-1][u][c^1]+dp[i][v][c])%mod;
else dp[i][v][c]=(dp[i-1][u][c]+dp[i][v][c])%mod;
//因为是双向边,所以两个方向都要更新
}
}
}
cout<<dp[k][t][0]<<endl;
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
题意:字符串 S S S, S S S只包含0或1,要求求出每个每个状态的 S S S,( S 一共有 2 N S一共有2^N S一共有2N个状态),其最短路的长度和。
最短路径要求如下:若 S i = 0 , i 这个点要经过偶数次,若 S i = 1 , i 这个点要经过奇数次 S_i=0,i这个点要经过偶数次,若S_i=1,i这个点要经过奇数次 Si=0,i这个点要经过偶数次,若Si=1,i这个点要经过奇数次。
2 ≤ N ≤ 17 2\leq N \leq 17 2≤N≤17.
由于N比较小,因此可以考虑把状态压缩, d [ i ] [ j ] 表示当前状态为 i ,且当前在点 j 时的最短路径 d[i][j]表示当前状态为i,且当前在点j时的最短路径 d[i][j]表示当前状态为i,且当前在点j时的最短路径,由于要求最短路径,可以用bfs来实现,与普通bfs不同的是,可以有多个起点,相当于多源bfs, 把所有初始点都要入队。
code:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ios std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define int long long
#define x first
#define y second
typedef pair<int,int> pii;
//head
const int N=18,mod=998244353;
int h[N*N],e[N*N],ne[N*N],idx;
int d[1<<N][N];//d[i][j],当前状态为i,当前在点j的最短路
queue<pii> q;
void add(int a,int b)
{
e[idx]=b; ne[idx]=h[a]; h[a]=idx++;
}
void bfs()
{
while(q.size())
{
auto t=q.front(); q.pop();
int u=t.y;
for(int i=h[u];~i;i=ne[i]){
int v=e[i];
int st=t.x^(1<<(v-1));
if(d[st][v]<2e9) continue;
d[st][v]=d[t.x][u]+1;
q.push({st,v});
}
}
}
void work()
{
int n,m;
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(a,b); add(b,a);
}
for(int i=0;i<1<<n;i++){
for(int j=0;j<=n;j++) d[i][j]=1e18;
}
for(int i=1;i<=n;i++) d[1<<(i-1)][i]=1, q.push({1<<(i-1),i});
//多源bfs
bfs();
int ans=0;
for(int i=1;i<(1<<n);i++){
int x=1e9;
for(int j=1;j<=n;j++) x=min(x,d[i][j]);
ans+=x;
}
cout<<ans<<endl;
}
signed main()
{
int t;
t=1;
while(t--) work();
return 0;
}