比赛链接:https://codeforces.com/contest/1295
题意:给n个火柴棍,问能拼出的最大的数是多少。
题解:1需要2根,7需要3根,
优先拼1 ,使位数足够多
但,如果n是奇数(全拿来拼1的话会余一根)且至少有3根,则优先拼一个7作为首位。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n;
scanf("%d",&n);
if((n&1)&&n>=3) {printf("7");n-=3;}
for(;n>=2;n-=2) printf("1");
puts("");
}
}
题意:给定n、x和一个长为n的01串s,s可以无限连接,问有多少个前缀的 cnt0-cnt1==x(cnt0是前缀中0的个数)。前缀包括一个空串,如果答案为无穷个则输出-1。
思路:参考了 https://blog.csdn.net/weixin_45757507/article/details/104112194
我认为T的某个倍数加目前此次遍历过程中0比1多的次数等于x的点就是答案存在的点,翻译成程序就是(x-d)%T==0与此同时我们还要保证此时(x-d)应该和T同号,否则随着子串的延长,会离答案越来越远,
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
char s[N];
int n,x,a[N];
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d%s",&n,&x,s+1);
int ans=0;
memset(a,0,sizeof a);
for(int i=1;i<=n;++i) a[i] = a[i-1] + (s[i]=='0'?1:-1) ;
if(!x) ++ans; //如果x为0,加上空串前缀
for(int i=1;i<=n;++i){
if(!a[n] && a[i]==x){ //如果末位为0,且串中有一位等于x,则答案是无穷
ans=-1;
break;
}
// a[n]*c1+a[i]==x --> (x-a[i])%a[n]==0 // (x-a[i])和a[n]必须同号
// a[n]*c1-a[i]==x
int k=x-a[i];
if(a[n] && k/a[n]>=0 && k%a[n]==0) ++ans;
//若a[n]==0 --> 如果 a[i]==0==x 无穷个答案,上面的情况;如果a[i] == 0 != x,那么a[i]对答案一定无贡献,不用考虑
}
printf("%d\n",ans);
}
}
题意:给两个字符串s和t,每次可从s中撷取子序列添到初始为空的字符串z的末尾,问最少要进行多少次这样的操作,z才能变成t?(0<|s|, |t|<=1e5,T<=100)
思路:n^2(二重循环,对着t从s里找)是会T的。
预处理出s各字母的下标,对t的每一位,到s的对应字母中二分查找 比 t的上一位在s中的对应下标 大的下标,如果该字母的所有下标找到头了,就++ans。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
char s[N],t[N];
int main(){
int T;
cin>>T;
while(T--){
scanf("%s%s",s+1,t+1);
vector<int>v[26];
for(int i=1;s[i];++i) v[s[i]-'a'].push_back(i);
int p=0,ans=1;//初始为1,第一段子序列
for(int i=1;t[i];++i){
int tmp=t[i]-'a';
if(!v[tmp].size()){ans=-1;break;}//不存在该字母
int pos=upper_bound(v[tmp].begin(),v[tmp].end(),p)-v[tmp].begin();//二分找下标
if(pos==v[tmp].size()){//没找到(没有更大的位置了)
++ans;
p=v[tmp][0];//从头开始
}else{
p=v[tmp][pos];
}
}
printf("%d\n",ans);
}
}
D. Same GCDs
题意:
思路:
代码:
题意:
思路:
代码:
F. Good Contest
题意:
思路:
代码: