A. Points On the Line
题意:数轴上有n个点,问最少去掉多少个点才能使剩下的点的最大距离为不超过k。
题解:排序后n^2枚举区间。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,k;
int a[maxn];
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
sort(a,a+n);
int ans=0;
int j;
for(int i=0;i<n;i++)
{
bool flag=0;
for(j=i;j<n;j++)
{
if(a[j]-a[i]>k)
{
ans=max(ans,j-i);
flag=1;
break;
}
}
if(!flag)
ans=max(ans,n-i);
}
printf("%d\n",n-ans);
return 0;
}
B. Our Tanya is Crying Out Loud
题意:给定整数n.k.a.b,规定将某数减一花费a,将某数除以k花费b,问将n变为1所需的最小花费。
题解:四个数都是2e9的范围。当n减小到小于k时,只能使用减一操作。否则就先减到距离n最近的k的倍数再除以k。注意两点,第一获取距离n最近的k的倍数的方法是n/k*k,第二在除以k的时候要判断除法花费是否比减去n-n/k要小。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 105
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
ll n,k,a,b;
ll Min(ll a,ll b)
{
return a<b?a:b;
}
int main()
{
cin>>n>>k>>a>>b;
ll ans=0;
if(k==1)
{
cout<<a*(n-1)<<endl;
return 0;
}
while(n!=1)
{
if(n<k)
{
ans+=a*(n-1);
break;
}
if(n%k!=0)
{
ans+=a*(n-n/k*k);
n=n/k*k;
}
ans+=Min(b,a*(n-n/k));
n/=k;
}
cout<<ans<<endl;
return 0;
}
C. Phone Numbers
题意:给出一个长度为n的串s,求一个长度为k、所有字符都在s中出现的串t,t的字典序大于s且字典序最小。
题解:如果k大于n,那么只需要添加一串最小的字母即可。否则记录下每个位置的字符的编号,用类似大数加法的方法将这个串的前k位加上1。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,k,num;
char s[maxn],t[maxn];
int p[maxn];
map<char,int>m;
int mo[26];
bool vis[26];
bool cmp(char a,char b)
{
return (a-'a')<(b-'a');
}
void sol()
{
cout<<s;
for(int i=n+1;i<=k;i++)
printf("%c",mo[0]+'a');
cout<<endl;
}
int main()
{
scanf("%d%d",&n,&k);
scanf("%s",s);
num=0;
for(int i=0;i<n;i++)
{
if(!vis[s[i]-'a'])
{
mo[num++]=s[i]-'a';
//m[s[i]]=num++;
vis[s[i]-'a']=1;
}
}
sort(mo,mo+num);
for(int i=0;i<num;i++)
m[mo[i]+'a']=i;
for(int i=0;i<n;i++)
p[i]=m[s[i]];
p[k-1]++;
for(int i=k-1;i>0;i--)
{
//p[i]++;
if(p[i]>=num)
{
p[i]%=num;
p[i-1]++;
}
}
if(k>n)
sol();
else if(p[0]>=num)
k++,sol();
else
{
for(int i=0;i<k;i++)
printf("%c",mo[p[i]]+'a');
printf("\n");
}
return 0;
}
D. Alena And the Heater
题意:给出一个数组a,规定串b的前4项为0,从第5项开始如果a的前面5项都大于r且b的前4项都为1,b的这项就为0;如果a的前面5项都小于l且b的前4项都为0,b的这项就为1;若都不满足就等于b的前一项。求一组符合条件的l和r。
题解:扫一遍数组a,中间依次用b更新l和r即可。
l=max(l,max(a[i],max(max(a[i-1],a[i-2]),max(a[i-3],a[i-4])))+1);
r=min(r,min(a[i],min(min(a[i-1],a[i-2]),min(a[i-3],a[i-4])))-1);
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>
#include<iostream>
#include<algorithm>
#define maxn 100050
#define INF 1e9
#define eps 1e-8
using namespace std;
typedef long long ll;
int n,a[maxn];
char b[maxn];
int l,r;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
scanf("%s",b);
l=-INF,r=INF;
for(int i=4;i<n;i++)
{
if(b[i]=='0')
{
if(b[i-1]-'0'+b[i-2]-'0'+b[i-3]-'0'+b[i-4]-'0'==4)
r=min(r,min(a[i],min(min(a[i-1],a[i-2]),min(a[i-3],a[i-4])))-1);
}
else
{
if(b[i-1]-'0'+b[i-2]-'0'+b[i-3]-'0'+b[i-4]-'0'==0)
l=max(l,max(a[i],max(max(a[i-1],a[i-2]),max(a[i-3],a[i-4])))+1);
}
}
printf("%d %d\n",l,r);
return 0;
}