A题:
题意:
给两个数n,k,求n的所有约数中第k小的数字是什么》
tip:
正常算的话肯定会超时,但是如果换一种思想,因为根号n的大小是不超过1e8的,那么就一定不会超时,所以求到根号n就可以把所有约数知道了,因为求一般的约数,另一半直接n/a[i]
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6+10;
int a[maxn];
void init(){
long long int n;
int k,ans = 0,flag = 0;
scanf("%I64d%d",&n,&k);
for(long long i = 1 ; i * i <= n ; i++){
if(n%i == 0){
a[++ans] = i;
if(i *i == n) flag = 1;
}
if(ans == k){
printf("%I64d\n",i);
return ;
}
}
if(flag == 0){
if(k>2*ans)
printf("-1\n");
else
printf("%I64d\n",(long long)n/a[2*ans-k+1]);
}
else{
if(k>2*ans-1)printf("-1\n");
else printf("%I64d\n",(long long)n/a[2*ans-k]);
}
}
int main(){
init();
return 0;
}
B题:
题意:
三个数字abc,a个电脑只有usb插口,b个电脑只有ps/2插口,c个电脑两个都有,然后给一些usb插口的鼠标,ps/2插口的鼠标,问最多能配多少个电脑,如果可以,价钱最少多少。
tip:
先把价钱排序,先把必须用某种鼠标的电脑配上,再算上都可以的,但是都可以的,因为排序的时候是单独排的,所以每次比较一下。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[10];
const int maxn = 3e5+10;
long long ans ;
int cntu,cntp,a[maxn],b[maxn],cnn;
void init(){
int p,u,c,m;
scanf("%d%d%d%d",&u,&p,&c,&m);
for(int i = 0 ; i < m ; i++){
int num;
scanf("%d%s",&num,s);
if(s[0] == 'U'){
a[cntu++] = num;
}
else if(s[0] == 'P'){
b[cntp++] = num;
}
}
sort(a,a+cntu);
sort(b,b+cntp);
int cntui = cntu,cntpi = cntp;
cntu = min(cntu,u);
cntp = min(cntp,p);
cnn = min(m-(cntu+cntp),c);
printf("%d ",cntu+cntp+cnn);
for(int i = 0 ;i < cntu ; i++){
ans+=a[i];
}
for(int i = 0 ; i < cntp;i++ )
ans+=b[i];
int cc = 0,i = cntu,j = cntp;
while(cc<cnn&&i<cntui&&j<cntpi){
if(a[i] > b[j]){
ans+=b[j];
j++;
}
else{
ans+=a[i];
i++;
}
cc++;
}
// printf("j = %d cntpi = %d\n",j,cntpi);
for(int k = i; k < cntui&&cc<cnn;k++,cc++) ans+=a[k];
for(int k = j; k < cntpi&&cc<cnn;k++,cc++) ans+=b[k];
printf("%I64d\n",ans);
}
int main(){
init();
return 0;
}
C题:
题意:
B串中去掉一段连续的,然后剩下的部分最长且是A的子串。
tip:
从前往后每个字母能依次对应A的哪里,前后往前也一样,最后枚举B这个串从前往后取到哪,从后往前取到哪。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e7;
int cnt1[maxn],cnt2[maxn],sler,srel;
char a[maxn],b[maxn];
void init(){
scanf("%s%s",a+1,b+1);
memset(cnt1,-1,sizeof(cnt1));
memset(cnt2,-1,sizeof(cnt2));
int lena = strlen(a+1),lenb = strlen(b+1);
int i = 1 ,j = 1;
for(i = 1 ; i <= lenb ; i++){
while(j <= lena&&b[i]!=a[j])
j++;
if(j == lena+1) break;
cnt1[i] = j++;
sler = i;
// printf("cnt1[%d] = %d\n",i,cnt1[i]);
}
int k = lena;
for(i = lenb ; i > 0 ; i--){
while(b[i]!=a[k]&&k > 0)
k--;
if(k == 0) break;
cnt2[i] = k--;srel = i;
// printf("cnt2[%d] = %d\n",i,cnt2[i]);
}
if(cnt1[1]==-1&&cnt2[lenb]==-1){
printf("-");
return;
}
if(cnt1[1] == -1){
for(int po = srel ;po <= lenb ;po++)
printf("%c",b[po]);
return;
}
if(cnt2[lenb] == -1){
for(int po = 1 ;po <= sler ;po++)
printf("%c",b[po]);
return;
}
int l = sler,r = lenb,ansl,ansr,ans = 0;
for(;l>=0;l--){
// printf("l = %d\n",l);
while(r>l&&cnt2[r]>cnt1[l]){
r--;
}
// printf("r = %d lenb = %d 1 = %d ans = %d\n",r,lenb,l+lenb-r,ans);
if(l+lenb-r>ans){
ans = l+lenb-r;
ansl = l;ansr = r+1;
}
}
for(int i = 1 ; i <= ansl ; i++) printf("%c",b[i]);
for(int j = ansr ; j <= lenb ;j++) printf("%c",b[j]);
}
int main(){
init();
return 0;
}