这次的A~D都是思维题,都比较简单。
A.Plus One on the Subset
题意:给定n个数,每次可以选择任意数量的数+1,求最短的+1次数使得全部的数字相等
题解:排序,因为最短次数就是让最小的跟最大的相等,所以输出最大的减去最小的即可。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N=1e2;
int a[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for (int i=0;i<n;i++) cin>>a[i];
sort (a,a+n);
cout<<a[n-1]-a[0]<<endl;
}
return 0;
}
B.Make AP
题意:给定3个数,不能改变顺序,可以选择任意一个数乘以一个正整数,问这三个数变化后(可以不变)能否成等差数列
题解:a,b,c三个数,求出b-a,c-b,如果这两个相等说明能变成等差数列。如果不相等,则先考虑变a,b-(c-b)就是a变化后的数,如果能整除a且是除以a后是正整数,则能变成等差数列。然后用相同的方式变b跟c
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
long long a,b,c;
cin>>a>>b>>c;
long long t1=c-b,t2=b-a,t3=(c-a)/2;
if (t1==t2)
{
cout<<"YES"<<endl;
continue;
}
bool flag=false;
if ((b-t1)%a==0 && b!=t1 && (b-t1)/a>0)
{
cout<<"YES"<<endl;
continue;
}
if ((b+t2)%c==0 && b-t2!=0 && (b+t2)/c>0)
{
cout<<"YES"<<endl;
continue;
}
if (t3*2==c-a && (c-t3)%b==0 && c!=t3 && (c-t3)/b>0)
{
cout<<"YES"<<endl;
continue;
}
cout<<"NO"<<endl;
}
return 0;
}
C.Division by Two and Permutation
题意:给定n个数,可以用ai/2向下取整来替代ai(不限次数),问能否让数组变成1n的数且1n每个数都要出现且仅出现一次
题解:先将小于n的数取出,然后再遍历,将ai变成小于n的数然后看看/2后是否出现过,如果没出现过则取出,出现过则继续往下/2知道变成0为止,如果变成0则说明不能满足题目要求,输出NO
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int N=55;
int a[N];
bool f[N];
bool p[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for (int i=0;i<n;i++)
{
cin>>a[i];
f[i+1]=true;
p[i]=true;
}
sort (a,a+n);
bool flag=true;
for (int i=0;i<n;i++)
if (a[i]<=n && f[a[i]])
{
p[i]=false;
f[a[i]]=false;
}else if (a[i]>n) break;
for (int i=0;i<n;i++)
{
if (p[i])
{
int t=a[i];
while(t>n) t=floor(1.0*t/2);
while(!f[t] && t>0)
{
t=floor(1.0*t/2);
}
if (t<=n && t>0 && f[t])
{
f[t]=false;
}else
{
flag=false;
break;
}
}
}
if (flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
D.Palindromes Coloring
题意:给定一个长度为n的字符串,从里面选出字母(不一定全选完),组成k个回文字符串后问最短的回文字符串的最大长度是多少
题解:统计每个字母的数量,然后将每个字母中两两为一对统计对数,因为要求最短的最大值,将这些组成一对的字母均分为k组,这样每一组的数量就是相同的都是最短的,多出来的字母全部变成单个的,如果个数大于k说明能在k组回文字符串中间加入这些字母,所以+1。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int a[27];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
string s;
cin>>s;
for (int i=0;i<27;i++) a[i]=0;
for (int i=0;i<s.length();i++) a[s[i]-'a']++;
int t1=0,t2=0;
for (int i=0;i<27;i++)
{
t2+=a[i]%2;
t1+=a[i]/2;
}
int p=t1%k,res=t1/k;
res*=2;
if (t2>=k) res++;
else if (p*2+t2>=k) res++;
cout<<res<<endl;
}
return 0;
}