题目:A. Yet Another Two Integers Problem
题意:直接差值模拟。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<ll,ll> PP;
const int MAXN=2e3+4;
int main() {
int T;
scanf("%d",&T);
while(T--) {
int a,b,ans=0;;
scanf("%d %d",&a,&b);
int temp=abs(a-b);
ans+=temp/10;temp%=10;
if(temp) ++ans;
printf("%d\n",ans);
}
return 0;
}
题目:B. Minimum Product
题意:给定四个整数a,b,x,y,已知 a > = x , b > = y a>=x,b>=y a>=x,b>=y。n次操作每次让a或者b减1,问 a ∗ b a*b a∗b的最小值。
分情况讨论 n > = ( a − x ) + ( b − y ) n>=(a-x)+(b-y) n>=(a−x)+(b−y)最小值就是 x ∗ y x*y x∗y。 设 ( a − k ) ∗ ( b − ( n − k ) ) , 并 且 ( k < = a − x , n − k < = ( b − y ) ) (a-k)*(b-(n-k)),并且(k<=a-x ,n-k<=(b-y)) (a−k)∗(b−(n−k)),并且(k<=a−x,n−k<=(b−y)),可知 ( a − k ) ∗ ( b − ( n − k ) ) (a-k)*(b-(n-k)) (a−k)∗(b−(n−k))函数开口向上,直接判断端点情况。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double ld;
ll a,b,x,y,n;
ll solve(ll k) {
return ((a-k)*(b-n+k));
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%lld %lld %lld %lld %lld",&a,&b,&x,&y,&n);
if(n>=((a-x)+(b-y))) {
printf("%lld\n",x*y);
}
else {
ll up=max(min(a-x,n),1ll*0);
ll down=min(n,max(1ll*0,y+n-b));
printf("%lld\n",min(solve(up),solve(down)));
}
}
return 0;
}
题目:C. Yet Another Array Restoration
题意:需要你构成一个等差数组,长度为n,n个数都不相同,让最大的数最小,输出数组。
给定了 x < y x
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<ll,ll> PP;
const int MAXN=2e3+4;
int a[100];
int ans[100];
int main() {
int T;
scanf("%d",&T);
while(T--) {
int n,x,y;
scanf("%d %d %d",&n,&x,&y);
if(n==2) {
printf("%d %d\n",x,y);
continue;
}
if(y-x-1==n-2) {
for(int i=x;i<=y;++i) {
printf("%d ",i);
}
printf("\n");
continue;
}
for(int d=1;d<=y-x;d++) {
if( (y-x)%d!=0 )
continue;
int temp=y%d;
if(!temp) temp+=d;
if(temp+(n-1)*d<=y && x+(n-1)*d>=y ) {
for(int j=y,cnt=1;cnt<=n;j-=d) {
printf("%d ",j); cnt++;
}
break;
}
else {
if(temp+(n-1)*d>y) {
for(int j=temp,cnt=1;cnt<=n;j+=d) {
printf("%d ",j); ++cnt;
}
break;
}
}
}
printf("\n");
}
return 0;
}
题目:D. Decrease the Sum of Digits
题意:每次可以让n加1,问最小的操作次数让n的所有位数之和小于等于s。
贪心,每次都处理低位的数字,直接给n进位减小各位数字总和,考虑极端情况有没有直接改变某一位成功的,比如711 和 3,从低位开始时289,直接是300,以此类推,从低位模拟即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<ll,ll> PP;
int book[30];
ll solve(ll x) {
ll ans=0;
while(x) {
ans+=x%10;
x/=10;
}
return ans;
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
ll n,s;
scanf("%lld %lld",&n,&s);
if(solve(n)<=s) {
printf("0\n");
continue;
}
ll ft=1,ans=0;
for(int i=1;i<=20;++i) {
ll now=(n/ft)%10;
if(now==0) {
ft*=10;
continue;
}
ll temp=ft*(10-now);
n+=temp;
ans+=temp;
ft*=10;
if(solve(n)<=s) {
break;
}
}
printf("%lld\n",ans);
}
return 0;
}
题目:E. Two Platforms
题意:给定n个点的坐标,让你找到两个平台即长度为k的恒定的y, x 2 − x 1 = k x2-x1=k x2−x1=k,问x在[x1,x2]区间的点数最多有多少。
可以知道和y并没有什么关系,sort一下n个点的x坐标,二分找右边第一个大于 x + k x+k x+k的点,找左边 x 0 = = x x0==x x0==x的点,预处理出以x点为左端点长度为k的平台的个数。
MAX[]数组维护 x + k x+k x+k之后最大的平台承载的点个数。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<ll,ll> PP;
int x[200010];
int book[200010];
int MAX[200010];
int main() {
int T;
scanf("%d",&T);
while(T--) {
int n,k;
scanf("%d %d",&n,&k);
for(int i=1;i<=n;++i)
scanf("%d",&x[i]);
for(int i=1;i<=n;++i) {
int o;scanf("%d",&o);
}
sort(x+1,x+1+n);
for(int i=1;i<=n;++i) {
int temp=x[i]+k;
int posr=upper_bound(x+1,x+1+n,x[i]+k)-x;
int posl=lower_bound(x+1,x+1+n,x[i])-x;
book[i]=posr-i+i-posl;
}
MAX[n+1]=MAX[n+2]=0;
for(int i=n;i>=1;--i) {
MAX[i]=max(MAX[i+1],book[i]);
}
int ans=1;
for(int i=1;i<=n;++i) {
int pos=upper_bound(x+1,x+1+n,x[i]+k)-x;
ans=max(ans,MAX[pos]+book[i]);
}
printf("%d\n",ans);
}
return 0;
}
题目:F. Subsequences of Length Two
题意:长度为n的字符串s,每一次操作可以改变字符为a-z任意一个,不超过k次,问最多s中能有几个子序列为t字符串。
直接划分状态集合,dp[i][j]:为前i个字符改变j次的最大值,我们还需要知道贡献的计算,再开一维表示t[0]的个数,直接进行转移。注意一下t[0]=t[1]的时候即贡献了t[0]数量,也给答案贡献了。
代码写的比较丑见谅。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<ll,ll> PP;
char S[222],T[3];
int dp[210][208][207];//前i个字符串 改变了j次 k个T[0]的个数 的 最大贡献
int main() {
memset(dp,-1,sizeof(dp));
int n,k;
int ans=0;
scanf("%d %d",&n,&k);
scanf("%s",S+1); scanf("%s",T);
for(int i=0;i<=n;++i) {
for(int j=0;j<=k;++j)
if(i==0)
dp[i][0][0]=0;
else dp[i][j][0]=0;
}
for(int i=1;i<=n;++i) {
for(int j=0;j<=k;++j) {
for(int kk=0;kk<=i;++kk) {
if(dp[i-1][j][kk]!=-1) {
dp[i][j][kk]=max(dp[i][j][kk],dp[i-1][j][kk]);
}
if(T[0]==T[1]) {
if(S[i]==T[0]) {
if(dp[i-1][j][kk]!=-1)
dp[i][j][kk+1]=max(dp[i][j][kk+1],dp[i-1][j][kk]+kk);
}
else {
if(j<k) {
if(dp[i-1][j][kk]!=-1)
dp[i][j+1][kk+1]=max(dp[i][j+1][kk+1],dp[i-1][j][kk]+kk);
}
}
ans=max(dp[i][j][kk],ans);
continue;
}
if(S[i]==T[0]) {
if(dp[i-1][j][kk]!=-1)
dp[i][j][kk+1]=max(dp[i][j][kk+1],dp[i-1][j][kk]);
}
else {
if(j+1<=k) {
if(dp[i-1][j][kk]!=-1)
dp[i][j+1][kk+1]=max(dp[i][j+1][kk+1],dp[i-1][j][kk]);
}
}
if(S[i]==T[1]) {
if(dp[i-1][j][kk]!=-1&&kk<i)
dp[i][j][kk]=max(dp[i][j][kk],dp[i-1][j][kk]+kk);
}
else {
if(j+1<=k) {
if(dp[i-1][j][kk]!=-1&&kk<i)
dp[i][j+1][kk]=max(dp[i][j+1][kk],dp[i-1][j][kk]+kk);
}
}
ans=max(dp[i][j][kk],ans);
}
}
}
printf("%d\n",ans);
return 0;
}