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 沒做出來 未完待續