A
知识点:排序/桶
题意:给一个数组,求其中所有不同非零元素的种类数。
解法一:对数组从小到大排序。很明显相同的元素排序后一定相邻,因此种类数=n-(相邻相等的对数)。注意要特判0是否存在。
时间复杂度O(nlogn),空间复杂度O(1)
解法二:注意到元素的范围是-1e5~1e5,因此可以开一个20万大小的桶数组用来存放每个元素是否出现。最后统计桶的数量即可(同样要特判0)。
时间复杂度O(n),空间复杂度O(2e5)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a[111111],i;
cin>>n;
int jud=0;
for(i=0;i<n;i++){
cin>>a[i];
if(a[i]==0)jud=1;
}
sort(a,a+n);
int cnt=0;
for(i=0;i<n-1;i++){
cnt+=(a[i]==a[i+1]);
}
cout<<n-cnt-jud;
}
B
知识点:模拟/贪心
题意:判断是否可以把’.‘字符改为’D’字符,把所有的’W’字符和’S’字符分隔开。若可以输出Yes并输出任意可行结果。否则输出No。
解法:只需要判断是否有相邻的W和S即可(注意要判断四个方向)。如果是Yes的情况,可以考虑贪心,把所有的’.'变成’D’即可。
#include<bits/stdc++.h>
using namespace std;
char a[555][555];
int main(){
int j,i,n,m;
cin>>n>>m;
for(i=0;i<n;i++)cin>>a[i];
int jud=0;
for(i=0;i<n;i++){
for(j=0;j<m;j++){
if(a[i][j]=='S'){
if(i>0){
if(a[i-1][j]=='W')jud=1;
else if(a[i-1][j]=='.')a[i-1][j]='D';
}
if(j>0){
if(a[i][j-1]=='W')jud=1;
else if(a[i][j-1]=='.')a[i][j-1]='D';
}
if(i<n){
if(a[i+1][j]=='W')jud=1;
else if(a[i+1][j]=='.')a[i+1][j]='D';
}
if(j<m){
if(a[i][j+1]=='W')jud=1;
else if(a[i][j+1]=='.')a[i][j+1]='D';
}
}
}
}
if(jud)cout<<"No";
else{
cout<<"Yes"<<endl;
for(i=0;i<n;i++)cout<<a[i]<<endl;
}
}
C
知识点:贪心
题意:找到a和b,使得a+b=n且a和b的所有数位上数字之和最大。求这个最大值。
解法:很明显,只需要a=9999…9即可(共有n的位数-1个9)。然后模拟计算最大值。
#include<bits/stdc++.h>
using namespace std;
int main(){
long long a,i;
cin>>a;
int t=0;
for(i=1;i<=a;i*=10)t++;
t--;
a-=i/10-1;
t*=9;
while(a){
t+=a%10;
a/=10;
}
cout<<t;
}
D
知识点:模拟
题意:找到给定数组的最长连续子数组,保证子数组的相邻两项a[i+1]<=2*a[i]。求这个最长的长度。
解法:按题意模拟即可。用一个cnt维护当前连续长度,max维护cnt的最大值。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,i;
int a[222222];
cin>>n;
for(i=0;i<n;i++)cin>>a[i];
int cnt=1,m=1;
for(i=0;i<n-1;i++){
if(a[i+1]<=a[i]*2)cnt++,m=max(m,cnt);
else{
cnt=1;
}
}
cout<<m;
}
E
知识点:贪心
题意:输入n和m,找到a和b,使得a和b的各数位数字之和不小于n,a+b的各数位数字之和不大于m
解法:令a+b=10000…000000即可。然后让a或b没有任何一位是0就可以了。我的解法是:
444444…445+555555…555=1000000…000
其中a和b都取2222位。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m,i;
cin>>n>>m;
for(i=0;i<2222;i++)cout<<4;
cout<<5<<endl;
for(i=0;i<2223;i++)cout<<5;
}
F
知识点:数论
题意:数组中取尽可能多的数,使它们的最大公约数不等于1。
解法:对于一些数的最大公约数不等于1的情况,很显然它们都拥有某个共同的素因子p。因此这道题就可以转为这样的思路:哪个素因子p在数组中出现的次数最多?(注:对于a[i]=p^k,也只计p出现了一次)。
因此可以开一个数组b[100000],其中b[i]代表素数i出现的次数(若i不是素数则为0)。最后求b数组的最大值即可。
统计的方式是对于每个a[i],对应的a[i]的每个出现的素因子p在b[p]里+1。
#include<bits/stdc++.h>
using namespace std;
int p[111111]={0};
int main(){
int n,i,a[111111];
cin>>n;
for(i=0;i<n;i++){
int x;
cin>>x;
for(int j=2;j*j<=x;j++){
if(x%j==0){
p[j]++;
while(x%j==0)x/=j;
}
}
if(x>1)p[x]++;
}
int m=1;
for(i=1;i<111111;i++)m=max(m,p[i]);
cout<<m;
}