https://codeforces.com/problemset/problem/1404/A
题意:给定一个长度为n的字符串s包含0 1 ?三种字符,?必须换成0或者1
问:是否每个长度为k的子串都含有相同个数的0和1
分析:对于此题,推导得知每个取模于k余数相同位置的字符必须相同,否则肯定为no
满足第一个条件后,判断在长度为k的区间内有无0或者1的个数超过了k/2,
有则no,无则yes
#include <bits/stdc++.h>
using namespace std;
#define N 300000+100
char s[N];
int vis[N];
int main()
{
int tt;
//freopen("in.txt","r",stdin);
for(cin>>tt;tt;tt--)
{
int n,k,cnt0=0,cnt1=0;
cin>>n>>k>>s+1;
for(int i=1;i<=k;i++)
vis[i]=-1;
for(int i=1;i<=n;i++)
{
int temp=(i-1)%k+1;
if(s[i]=='?')
continue;
if(vis[temp]!=-1&&s[i]-'0'!=vis[temp])
{
cout<<"NO"<<endl;
goto x;
}
else if(vis[temp]==-1)
vis[temp]=s[i]-'0';
}
for(int i=1;i<=k;i++)
{
cnt0+=(vis[i]==0);
cnt1+=(vis[i]==1);
}
if(cnt0<=k/2&&cnt1<=k/2)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
x:;
}
return 0;
}
https://codeforces.com/problemset/problem/1624/D
题意:给定一个字符串,要求搞出k个回文串,并且让这k个回文的最小长度最大
分析:最小长度最大,答案单调,所以锁定为二分答案
#include <bits/stdc++.h>
using namespace std;
int a[30];
int n,k;
bool check(int len)
{
int cnt=0,x=len/2,tot=0;
for(int i=1;i<=26;i++)
{
cnt+=a[i]/2;
}
if(x*k>cnt)
return 0;
if(len%2==0)
return 1;
for(int i=1;i<=26;i++)
{
tot+=a[i];
}
if(tot>=k*len)
return 1;
else
return 0;
}
int main()
{
int t;
// freopen("in.txt","r",stdin);
for(cin>>t;t;t--)
{
cin>>n>>k;
for(int i=0;i<30;i++)
a[i]=0;
char ch;
for(int i=1;i<=n;i++)
{
cin>>ch;
a[(int)(ch-'a'+1)]++;
}
int l=1,r=n/k;
while(r>l)
{
int mid=(l+r+1)>>1;
if(check(mid))
{
l=mid;
}
else
{
r=mid-1;
}
}
cout<<l<<endl;
}
return 0;
}
https://codeforces.com/contest/1352/problem/E
题意:给定长度为n的数组,如果数组中元素等于长度至少为2的子段和,那么这个元素是特别的。
问有多少特别的元素
分析:n给定1e4,锁定n2方法,利用前缀和能枚举出所有子段长度,根据题意利用数组哈希进行与原数组的匹配
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int sum[10000];
int a[10000];
int main()
{
int t;
// freopen("in.txt","r",stdin);
for(cin>>t;t;t--)
{
int n,maxx=0;
cin>>n;
for(int i=1,temp;i<=n;i++)
{
cin>>temp;
maxx=max(maxx,temp);
a[temp]++;
sum[i]=temp+sum[i-1];
}
int ans=0;
for(int i=0;i<=n;i++)
{
for(int j=i+2;j<=n;j++)
{
if(sum[j]-sum[i]>maxx)
continue;
if(a[sum[j]-sum[i]]!=0)
{
ans+=a[sum[j]-sum[i]];
a[sum[j]-sum[i]]=0;
}
}
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)
{
sum[i]=a[i]=0;
}
}
return 0;
}
https://codeforces.com/contest/1654/problem/C
题意:如果分蛋糕会把蛋糕分为原重量的,一半向下取整和一半向上取整,那么给出了一些被切好的蛋糕,判断这些蛋糕是否可以由一块蛋糕切分而来
分析:将所有蛋糕加和,然后每一次切最大的那一块,如果切出来的蛋糕重量和给出的一系列蛋糕中重量一样,那么就不要再对这个蛋糕切分了。
注意最多切n-1次
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
int t;
// freopen("in.txt","r",stdin);
for(cin>>t;t;t--)
{
int n;
priority_queue<ll>q;
map<ll,int>mp;
long long temp,sum=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>temp;
sum+=temp;
mp[temp]++;
}
q.push(sum);
int cnt=0;
while(!q.empty())
{
ll now=q.top();
q.pop();
if(mp[now])
{
mp[now]--;
continue;
}
if(cnt>=n)
break;
q.push(now/2);
q.push((now+1)/2);
cnt++;
}
bool falg=true;
for(auto x:mp)
{
if(x.second!=0)
{
cout<<"NO"<<endl;
falg=false;
break;
}
}
if(falg)
{
cout<<"YES"<<endl;
}
}
return 0;
}