Codeforces Round 903 (Div. 3)ABCDE
A. Don't Try to Count
题意:复制\(s\)串若干遍,是否能在\(s\)串中找到\(t\)串。
思路:直接暴力,注意不要超限,会MLE
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int ns[30],nt[30];
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int t; cin>>t;
while(t--)
{
int n,m; cin>>n>>m;
string s,t; cin>>s>>t;
for(int i = 0;i <= 30; i++)
ns[i] = nt[i] = 0;
for(int i = 0;i < n; i++)
ns[s[i]-'a']++;
for(int i = 0;i < m; i++)
nt[t[i]-'a']++;
bool ok = true;
for(int i = 0;i < 26; i++)if(nt[i]&&!ns[i]){
ok = false;
break;
}
if(!ok)
cout<<"-1\n";
else{
bool ok = false;
int cnt = 0;
while(1)
{
if(cnt>10)break;
if(s.find(t) != string::npos)
{
ok = true;
break;
}
s = s + s;
cnt++;
}
if(ok)cout<<cnt<<"\n";
else cout<<"-1\n";
}
}
return 0;
}
B. Three Threadlets
题意:给你3根绳子,问你能否在3刀以内(可以为0刀),使得所有绳子一样长。
思路:分析一下,我们最终一定会变成当前最短的,如果变不成,那一定不行。因为如果不变成当前最短的,那么意味着当前最短的要被切,那么其他的不可能在剩余2刀之内切成一样,除非原本三个都和最短的一样长。
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int t; cin>>t;
while(t--)
{
ll a,b,c;
cin>>a>>b>>c;
ll minn = min({a,b,c});
if(a%minn||b%minn||c%minn)
cout<<"No\n";
else{
int ans = 0;
if(a!=minn)
ans += a/minn-1;
if(b!=minn)
ans += b/minn-1;
if(c!=minn)
ans += c/minn-1;
if(ans>3)
cout<<"No\n";
else cout<<"Yes\n";
}
}
return 0;
}
C. Perfect Square
题意:给你一个初始矩阵,问你如果要该矩阵旋转90°之后和原来的一样,最少要操作多少次。每次操作可以选择一个让他变成下一个(z的话就不变了)
思路:旋转后\(a[i][j],a[j][N-i+1],a[N-i+1][N-j+1],a[N-j+1][i]\)是要一样的,那么,我们考虑变成这四个中最大的(因为只能往大的变),统计答案即可。
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
char s[1010][1010];
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int t; cin>>t;
while(t--)
{
int n; cin>>n;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++)
cin>>s[i][j];
ll ans = 0;
int m = n/2;
/*
a[i][j] -> a[j][N-i+1]
↑ ↓
a[N-j+1][i]<-a[N-i+1][N-j+1]
*/
for(int i = 1;i <= m; i++)
{
for(int j = i; j < n-i+1; j++)
{
char a[4] = {s[i][j],s[j][n-i+1],s[n-i+1][n-j+1], s[n-j+1][i]};
char mx = a[0];
for(int k = 1;k < 4; k++)
mx = max(mx,a[k]);
for(int k = 0;k < 4; k++)
ans += mx-a[k];
}
}
cout<<ans<<"\n";
}
return 0;
}
D. Divide and Equalize
题意:给你一个数组\(a\)包含\(n\)个正整数。每次你可以选择任意两个元素\(a_i,a_j\),然后让\(a_i/x,aj*x\)(这里\(x\)整除\(a_i\))。问能否使得所有元素都变得一样。
思路:根据唯一分解定理,我们对每个数进行质因数分解。最后我们的每种质因子一定要可以平均分配才能使得所有数一样。
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int a[N];
map<int,int>mp;
void primer(ll x)
{
for (ll i = 2; i <= x / i; i++)
{
if (x % i == 0)
{
int s = 0;
while (x % i == 0)
{
x = x / i;
s++;
}
mp[i]+=s;
}
}
if (x > 1)mp[x]++;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int t; cin>>t;
while(t--)
{
mp.clear();
int n; cin>>n;
for(int i = 1;i <= n; i++)
cin>>a[i],primer(a[i]);
bool ok = true;
// for(auto [x,c]:mp)
// cout<<x<<" "<<c<<"\n";
for(auto [x,c]:mp)if(c%n&&x!=1){
ok = false;
break;
}
if(ok)cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}
E. Block Sequence
题意:给你一个序列\(a\)长度为\(n\)。我们定义:我们可以把元素分成第一个元素长度的块的叫做美丽数组。问最少操作多少次能变得美丽。
思路:dp。我们知道,当前的和后面的有关,我们考虑倒着dp。
定义:\(dp[i]\):\(i~n\)最少删多少个是美丽的。
转移:
考虑删掉:\(dp[i] = dp[i+1]+1\)
考虑保留:\(if(i+a[i]\le n) dp[i] = dp[i+a[i]+1]\)
// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
ll a[N],dp[N];
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr);
int t; cin>>t;
while(t--)
{
int n; cin>>n;
for(int i = 1;i <= n; i++)
cin>>a[i];
dp[n] = 1,dp[n+1] = 0;
for(int i = n-1;i >= 1;i--)
{
dp[i] = dp[i+1]+1;//删除
if(a[i]<=n-i)//保留
dp[i] = min(dp[i],dp[i+a[i]+1]);
}
cout<<dp[1]<<"\n";
}
return 0;
}