Codeforces Round #667 (Div. 3)
题外话
恢复性训练
A
题意
通过对a或者b加若干个k(这个k只要是1-10之间的数就行,每次只能加一个k,且每次加的k可以不一样),使a,b相等,问需要用的k 的总和
思路
直接找max(a,b)和min(a,b),然后用max 的数除以min 的数 ,然后加上max的数 % min的数
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
#ifdef zerol
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
#else
#define dbg(...)
#endif
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =5e5+10;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[N],dr[N],w[N];
LL i,j,g;set<int >v;
const int maxp = 1e5;
void answer(){
cin >>n>>m;
LL ma = max(m,n);
LL mi =min(m,n);
if(m==n){
cout<<0<<endl;
return ;
}
if((ma-mi)%10==0){
cout<<(ma-mi)/10<<endl;
}
else {
cout<<(ma-mi)/10+1<<endl;
}
return ;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
int t;cin >>t;
while(t--)answer();
return 0;
}
B
题意
给你一个a, b 和x, y 。并且 a>=x && b >= y 的问你通过对 a 或者 b 进行 n次减一 之后 a* b 的 最小值 是多少
思路
先思考有几种情况,我们会很快的发现
- 第一种情况就是 n 大于 a-x + b-y
- 然后,顺着想,一定会想到,剩下的情况就是只对一个数进行操作直到无法操作之后换一个数,最后判断min
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
#ifdef zerol
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
#else
#define dbg(...)
#endif
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =5e5+10;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[N],dr[N],w[N];
LL i,j,g;set<int >v;
const int maxp = 1e5;
void answer(){
LL a, b, x,y;
cin >>a>>b>>x>>y>>n;
if(a-x+b-y<=n){
cout<<x*y<<endl;
return ;
}
LL m1 =0 , m2 =0 ;
if(a-x<n) m1 = x * (b-n+(a-x));
else m1 = (a-n)*b;
if(b-y<n) m2 = y*(a-n+(b-y));
else m2 = (b-n)*a;
cout<<min(m1,m2)<<endl;
return ;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
int t;cin >>t;
while(t--)answer();
return 0;
}
C
题意
这个题,审题审了半天,最后看题解人家写的题意 ,才弄明白说的啥意思。。。
就是给你个x,y,让一个非负数组,且这个数组是单调递增包含x,y,问你构造出这个数组的 d最小 的情况(就是一个等差数列)
思路
- 那么通过题意了解之后, 肯定想要超级暴力的做法, 然后看看范围,发现 $ O((n)^3) $ 是可以的,所以直接暴力做就可以
- 暴力的方法就是先确定一个开始的 a[0] ,然后在确定一个 d ,之后判断x, y 是否在这个数组里,在的话判断一下这个数组的最后一个数和已有的数组最后一个数的大小(一般来说最后一个数越小,d就越小)
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
#ifdef zerol
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
#else
#define dbg(...)
#endif
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =5e5+10;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[N],dr[N],w[N];
LL i,j,g;set<int >v;
const int maxp = 1e5;
void answer(){
cin >>n>>k>>m;
if(n==2)cout<<k<<" "<<m<<endl;
else{
cl(ar);cl(br);
for(int i=1 ;i<=50;i++){
br[1] = i;
for(int j=1;j<=50;j++){
for(int g = 1;g<n;g++)br[g+1] = br[1]+j*g;
int ok1 =0 , ok2=0 ;
for(int g= 1 ;g<=n;g++){
if(k == br[g])ok1=1 ;
if(m == br[g])ok2= 1 ;
}
if(ok1 && ok2 ){
if(ar[n]>br[n]||ar[n] ==0)
for(int g=1 ;g<=n;g++)ar[g] = br[g];
}
}
}
for(int i=1 ;i<=n;i++)cout<<ar[i]<<" ";cout<<endl;
}
return ;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
int t;cin >>t;
while(t--)answer();
return 0;
}
D
题意
给你两个数, 一个是n ,一个是m 让你把n的所有数位上的数字相加之后 less than(小于等于) m , 如果不行的话,就加数使得改变的n 所有数位上的数字相加之后 less than(小于等于) m
思路
不用想的太麻烦,直接暴力思维考虑,因为n 的范围是 $ (10)^{18} $ ,所以n 的位数最多也就是18 , 完全可以通过 $ O(n)^2 $ 的算法通过,
- 即从最后一个数开始判断 加上补全的数字之后是否会 less than m
- 如果 还是大于的话, 就移动到倒数第二位的数字,进行补全, 直到第一个数,也不行的时候在扩充一位数
代码
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
#ifdef zerol
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
#else
#define dbg(...)
#endif
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =5e5+10;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[N],br[N],cr[N],dr[N],w[N];
LL i,j,g;set<int >v;
const int maxp = 1e5;
LL resu(LL x){
int sum =0 ;
while(x){
sum+=x%10;
x/=10;
k ++ ;
}
return sum ;
}
void answer(){
cin>>n>>m;
LL sum =0 ,result =0 ;
k =0 ;
sum = resu(n);
if(sum<=m){
cout<<0<<endl;
return ;
}
// cout<<sum<<endl;
// cout<<k<<endl;
LL cnt =k , num = n ;
// cout<<num<<endl;
for(int i=1;i<=cnt+1;i++){
LL res =0 , lueluelue =1 ;
for(int j =1 ;j<i;j++)lueluelue*=10;
res = num%lueluelue;
result += lueluelue- res ;
// cout<<res<<" "<<sum<<endl;
sum=resu(num+(lueluelue- res));
num+=(lueluelue- res);
// cout<<result<<endl;
if(sum<=m){
cout<<result<<endl;
return ;
}
}
return ;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
int t;cin >>t;
while(t--)answer();
return 0;
}
E
题意
给你一堆坐标,问你用两条平行于y 的两个长度为k 的线段最多能留下几个点
思路
用样例模拟的时候,会发现其实y是没有用的, 只需要对x进行递增排序然后通过 二分预处理 找到第一条线段的留下的点数, 之后直接通过预处理之后的数组得出第二条留下的点数
代码
// 注意 数组空间开太大的话,memset会用很长的时间, 来自一个因为memset疯狂超时的不愿透露姓名的菜鸡
#include <cstdio>
#include <algorithm>
#include<iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
#include<stack>
#include <cassert>
#include<map>
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define pb push_back
#define de(x) cerr<<#x<<" = "<<x<<endl
#define __i __int128
#define FOR(i, x, y) for (decay<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
#define FORD(i, x, y) for (decay<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
#ifdef zerol
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0)
#else
#define dbg(...)
#endif
using namespace std;
//using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pLL;
const int inf=0x7fffffff;
const int N =5e5+10;
const int maxn = 200010;
void clear(unsigned char *pta, int size )
{//结构体初始化
while(size>0)
{
*pta++ = 0;
size --;
}
}
LL n, k, m ;
LL ar[200005],br[200005];
LL i,j,g;
const int maxp = 1e5;
void answer(){
cin>>n>>m;
LL ans =0 ;
cl(br);
for(int i=1;i<=n;i++)cin >>ar[i];
for(int i=0;i<n;i++)cin >>k;
sort(ar+1,ar+1+n );
for(int i=n;i>=1;i--){
int s = ar[i]+m;
j = upper_bound(ar+1,ar+1+n,s)-ar;
br[i] = max(br[i+1] , j-i);
}
for(int i=1 ;i<=n;i++){
int s = ar[i]+m;
j = upper_bound(ar+1,ar+1+n,s)-ar;
ans = max(ans , j-i + br[j]);
}
cout<<ans<<endl;
return ;
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0), cout.tie(0);
int t;scanf("%d",&t);
while(t--)answer();
return 0;
}