https://codeforces.com/contest/1295
A 题意: 问共有n个火柴可以组成的最大数字
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100010;
int main()
{
int t,n;
cin>>t;
while(t--)
{
cin>>n;
if(n%2==0)
{
n/=2;
for(int i=0;i<n;i++)
cout<<1;
cout<<endl;
}
else
{
n/=2;
cout<<7;
for(int i=1;i<n;i++)
cout<<1;
cout<<endl;
}
}
return 0;
}
B 这一题实在是太坑了 题意太难懂了 看了有半多小时才弄懂了。。。。
题意 给你一个无限字符串的循环部分 定义一个字符串前缀的平衡值为0的数量-1的数量 问这个无限字符串共有多少个前缀的平衡等 x 。输出前缀的数量 字符串可以为负 无限个前缀输出 -1 空前缀为真
空前缀的平衡等于0 那么如果x==0直接ans++就好 当时还没想到。。其他的情况空前缀不影响 接下来就要对循环部分处理了 开dp数组保存当前位置前缀的平衡。
很容易想到(x-dp[i])%dp[size-1]0 这种情况 需要注意值可能为负 就会出现错误 需要判断两个值同号 如果xdp[i] 一定也是可以的 所以 判断 (x-dp[i])/dp[size-1]>=0
就可以当时还漏了一种情况 如果有x-dp[i]==0且dp[size-1]==0 那么会有无限多个
输出-1
```cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100010;
string s;
int main()
{
int t,n;
cin>>t;
while(t--)
{
cin>>n>>x;
cin>>s;
int dp[maxn];
int cnt0=0,cnt1=0;
n=s.size();
for(int i=0;i<n;i++)
{
if(s[i]=='0') cnt0++;
else cnt1++;
dp[i]=cnt0-cnt1;
}
bool flag=0;
int res=dp[n-1],ans=0;
for(int i=0;i<s.size();i++)
{
if(x==dp[i]&&!res) flag=1;
if(res&&abs(x-dp[i])%abs(res)==0&&(x-dp[i])/res>=0)
ans++;
}
if(!x) ans++;
if(flag) cout<<-1<<endl;
else
cout<<ans<<endl;
}
return 0;
}
C
初始字符串 z为空 已知字符串s 每次可以从字符串s复制一段子序列加到z之后 问最少需要几次才能得到 串t 已知字符全部是小写字母
首先开一个不定数组 ve[26] 保存每个字母在串s中的位置 从前向后遍历s更新ve
ve内一定是单增的序列 遍历串t 寻找当前字母在s中的位置如果比前一个字母位置大继续遍历下一个 否则ans++继续寻找当前字母从s的初始位置开始 因为ve是单增的所以可以二分寻找 upper_bound()
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int main()
{
int t;
cin>>t;
while(t--)
{
string s,t;
vector<int> ve[26];
cin>>s>>t;
for(int i=0;i<s.size();i++)
ve[s[i]-'a'].push_back(i);
bool flag=1;
for(int i=0;i<t.size();i++)
if(ve[t[i]-'a'].size()==0 )
{
flag=0;break;//有字母未出现 不可能完成
}
if(flag)
{
int ans=1;
for(int i=0,j=-1;i<t.size();i++)
{
int x=t[i]-'a';
auto v=upper_bound(ve[x].begin(),ve[x].end(),j);//返回 v是一个迭代器
if(v==ve[x].end())
{
j=-1;ans++;i--;//当前字母未找到还要从这个位置开始 所以i--
}
else j=*v;
}
cout<<ans<<endl;
}
else puts("-1");
}
return 0;
}
D 没做出来 未完待续