Codeforces Round 903 (Div. 3)
A.
按题意模拟
字符串find函数
if(x.find(s)==string::npos)//没找到
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int n,m;cin>>n>>m;
string x,s;cin>>x>>s;
int cnt=0;
while(x.size()<100){
if(x.find(s)==string::npos){
x=x+x;cnt++;
}else{
cout<<cnt<<'\n';
return ;
}
}
cout<<"-1\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
B.
先排序,再判大数是不是小数的整数倍,若不是则NO
再计算出割断的次数,小等于3才是YES
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int a[5];
for(int i=1;i<=3;i++)cin>>a[i];
sort(a+1,a+1+3);
int cnt=0;
for(int i=2;i<=3;i++){
if(a[i]%a[1]!=0){
cout<<"NO\n";return ;
}
cnt+=a[i]/a[1]-1;
}
if(cnt<=3)cout<<"YES\n";
else cout<<"NO\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
C.
找到点(i,j)旋转后的其他3个位置,取最大值
算出操作次数即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e3+10;
#define inf 0x3f3f3f3f
int g[N][N];
void solve() {
int n;cin>>n;
char c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>c;
g[i][j]=c-'a';
}
int cnt=0;
for(int i=1;i<=n/2;i++){
for(int j=1;j<=n/2;j++){
int ma=max({g[i][j],g[n-j+1][i],g[j][n-i+1],g[n-i+1][n-j+1]});
int tmp=g[i][j]+g[n-j+1][i]+g[j][n-i+1]+g[n-i+1][n-j+1];
cnt+=ma*4-tmp;
}
}
cout<<cnt<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
D.
考虑把所有数都进行质因数分解(分成最小单位)
然后看每种质因数是否都有n的整数倍个,这样一定能通过若干操作后使每个数相同
类似于守恒
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
#define inf 0x3f3f3f3f
void solve() {
int n;cin>>n;
map<int,int>mp;
for(int i=1,x;i<=n;i++){
cin>>x;
//cout<<"x="<<x<<'\n';
mp[1]++;
for(int j=2;j*j<=x;j++){
if(x%j==0){
while(x%j==0){
mp[j]++;
x/=j;
//cout<<j<<'\n';
// cout<<"x="<<x<<'\n';
}
//cout<<"x="<<x<<' '<<"j="<<j<<'\n';
}
}
//cout<<'\n';
if(x>1)mp[x]++;
}
for(auto t:mp){
if(t.second%n==0)continue;
cout<<"NO\n";return ;
}
cout<<"YES\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
E.
从后往前dp,看当前数作为区间开头能否更优,否则就删掉
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
#define inf 0x3f3f3f3f
int a[N];
void solve() {
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
vector<int>dp(n+10,0);
dp[n]=1;dp[n+1]=0;
for(int i=n-1;i>=1;i--){
if(i+a[i]<=n){
dp[i]=min(dp[i+a[i]+1],dp[i+1]+1);
}else{
dp[i]=dp[i+1]+1;
}
}
cout<<dp[1]<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}
F.
首先,最远考虑直径,再最小考虑直径的中间值
问题转化成距离最远的两个标记点的一半
那么就是标记点之间的直径的一半
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
#define inf 0x3f3f3f3f
int n,k;
vector<int>vis;
vector<vector<int>>g;
int d1,d2;
int dep_d1,dep_d2;
void dfs1(int u,int fa,int dep){
if(vis[u]&&dep>dep_d1){
dep_d1=dep;
d1=u;
}
for(int i=0;i<g[u].size();i++){
int y=g[u][i];
if(y==fa)continue;
dfs1(y,u,dep+1);
}
}
void dfs2(int u,int fa,int dep){
if(vis[u]&&dep>dep_d2){
dep_d2=dep;
d2=u;
}
for(int i=0;i<g[u].size();i++){
int y=g[u][i];
if(y==fa)continue;
dfs2(y,u,dep+1);
}
}
void solve() {
dep_d1=0;dep_d2=0;
cin>>n>>k;
vis=vector<int>(n+1);
g=vector<vector<int>>(n+1);
for(int i=1,x;i<=k;i++){
cin>>x;
vis[x]++;
}
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
if(n==1||k==1){
cout<<"0\n";return ;
}
if(n==2){
cout<<"1\n";return ;
}
for(int i=1;i<=n;i++){
if(vis[i]){
dfs1(i,0,1);
// cout<<"i="<<i<<'\n';
break;
}
}
dfs2(d1,0,1);
// cout<<"d1="<<d1<<' '<<"d2="<<d2<<'\n';
cout<<dep_d2/2<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int left=1;
cin>>left;
while(left--){
solve();
}
}