Codeforces Round #667 (Div. 3)
CF1409A Yet Another Two Integers Problem
分析
尽量填大的,那就是\(\lceil\frac{|a-b|}{10}\rceil\)
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed main(){
for (rr int T=iut();T;--T){
rr int A=iut(),B=iut(),C;
if (A<B) C=B-A; else C=A-B;
print(C/10+((C%10)>0)),putchar(10);
}
return 0;
}
CF1409B Minimum Product
分析
题目可以转换成找到一个\(k\),最小化
\((a-k)*(b-(n-k)),a-k\geq x,b-(n-k)\geq y\)
最小化的答案可以化简成
\(-k^2+(a+n-b)k+a(b-n)\)
且\(\max\{y+n-b,0\}\leq k\leq \min\{a-x,n\}\)
由于它是个开口向下的二次函数,那么最小值应在左右边界之一
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long lll;
inline lll iut(){
rr lll ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline lll min(lll a,lll b){return a<b?a:b;}
inline lll max(lll a,lll b){return a>b?a:b;}
signed main(){
for (rr int T=iut();T;--T){
rr lll A=iut(),B=iut(),X=iut(),Y=iut(),
n=min(iut(),A-X+B-Y),mn=max(n-B+Y,0),mx=min(A-X,n);
rr lll ans=A*(B-n)+min(mn*(A-B+n-mn),mx*(A-B+n-mx));
print(ans),putchar(10);
}
return 0;
}
CF1409C Yet Another Array Restoration
分析
题目也就是要找到尽量大的公差,
使得\(x,y\)在当中的前\(n\)项,
直接枚举即可
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed main(){
for (rr int T=iut();T;--T){
rr int n=iut(),A=iut(),B=iut();
rr int ans=1e9,ans1,ans2;
for (rr int st=1;st<=A;++st)
for (rr int i=1;i<=B-A;++i)
if (!((A-st)%i)&&!((B-st)%i)){
if ((B-st)/i+1>n) continue;
if (ans>st+i*(n-1)){
ans=st+i*(n-1);
ans1=st,ans2=i;
}
}
for (rr int i=0;i<n;++i)
print(ans1+ans2*i),putchar(i==n-1?10:32);
}
return 0;
}
CF1409D Decrease the Sum of Digits
分析
显然把某一位加1再将后面的位置赋0或者原数才是最优的
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long lll;
inline lll iut(){
rr lll ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline lll dig(lll n){
rr lll ans=0;
for (;n;n/=10) ans+=n%10;
return ans;
}
signed main(){
for (rr int T=iut();T;--T,putchar(10)){
rr lll n=iut(),s=iut(),now;
if (dig(n)<=s) putchar(48);
else{
for (rr lll i=10;;i*=10)
if (dig(now=(n/i+1)*i)<=s){
print(now-n); break;
}
}
}
}
CF1409E Two Platforms
分析
双指针处理前缀最大值和后缀最大值判断即可
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=200011;
int n,m,a[N],b[N],TOT,CNT[N],p[N],o[N],Pre[N],Suf[N],ans;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed main(){
for (rr int T=iut();T;--T){
n=iut(),m=iut(); ans=0;
for (rr int i=1;i<=n;++i) b[i]=a[i]=iut();
for (rr int i=1;i<=n;++i) CNT[i]=0,iut();
sort(b+1,b+1+n),TOT=unique(b+1,b+1+n)-b-1;
for (rr int i=1;i<=n;++i) ++CNT[lower_bound(b+1,b+1+TOT,a[i])-b];
for (rr int i=1;i<=TOT;++i) CNT[i]+=CNT[i-1];
for (rr int i=1,j=1;i<=TOT;++i){
for (;j<=i&&b[j]<b[i]-m;++j);
o[i]=CNT[i]-CNT[j-1];
}
for (rr int i=TOT,j=TOT;i;--i){
for (;j>=i&&b[j]>b[i]+m;--j);
p[i]=CNT[j]-CNT[i-1];
}
Pre[0]=Suf[TOT+1]=0;
for (rr int i=1;i<=TOT;++i) Pre[i]=max(Pre[i-1],o[i]);
for (rr int i=TOT;i;--i) Suf[i]=max(Suf[i+1],p[i]);
for (rr int i=1;i<=TOT;++i) ans=max(ans,Pre[i]+Suf[i+1]);
print(ans),putchar(10);
}
return 0;
}
CF1409F Subsequences of Length Two
分析
设\(dp[n][m][k]\)表示当前匹配的位置为\(n\),
与\(t[0]\)相同的个数为\(m\),剩余次数为\(k\)的答案
也许记忆化搜索更为直观一点吧
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
int dp[211][211][211],n,m; char s[211];
inline signed max(int a,int b){return a>b?a:b;}
inline signed Dp(int dep,int now,int m){
if (dep>n) return 0;
if (~dp[dep][now][m]) return dp[dep][now][m];
rr int ans=now*(s[dep]==s[n+2])+Dp(dep+1,now+(s[dep]==s[n+1]),m);
if (m>0){
ans=max(ans,Dp(dep+1,now+1,m-1));
ans=max(ans,now+Dp(dep+1,now+(s[n+1]==s[n+2]),m-1));
}
return dp[dep][now][m]=ans;
}
signed main(){
scanf("%d%d",&n,&m);
memset(dp,-1,sizeof(dp));
for (rr int i=1;i<=n+2;++i){
rr char c=getchar();
while (!islower(c)) c=getchar();
s[i]=c;
}
return !printf("%d",Dp(1,0,m));
}