这次队长说题目不会像上次一样做的那么顺,,,出了很多看上去像是cf上的题,结果发现是很古早的cf Div3。。。
目录
C-Yet Another Array Restoration
E-Yet Another Two Integers Problem
A-Decrease the Sum of Digits
给出n,求最少经过几次操作n的各位数之和小于等于s。
思路:分类讨论:1、原来的n各位数之和小于s,输出0;2、若各位数之和大于s,因为要求最小次数,则进位应该是最少次。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
int t,s;
ll n,ans;
ll pmod(ll a,ll b)
{
ll res=1;
while(b)
{
if(b%2) res=res*a;
b/=2;
a=a*a;
}
return res;
}
int pan(ll n,int s)
{
int ans=0;
while(n)
{
ans+=n%10;
n/=10;
}
return ans;
}
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
cin>>t;
while(t--)
{
cin>>n>>s;
ll sum=pan(n,s);
if(sum<=s) cout<<"0"<<'\n';
else
{
int cnt=0;
bool flag=0;
ll l=n;
while(n)
{
sum-=n%10;
cnt++;
n/=10;
if(sum+1<=s)
{
flag=1;
break;
}
}
if(flag)
{
if(n) ans=(n+1)*pmod(10,cnt)-l;
else ans=pmod(10,cnt)-l;
}
cout<<ans<<'\n';
}
}
return 0;
}
B - Two Platforms
给出n个点的横纵坐标,以及两个平面的长度,点的横坐标在平面的范围内时可以被平面接住,问两平面最多可以接住多少个点。
思路:很容易得知,解题与y坐标无关,将x坐标由小到大排序,枚举第一块木板从第i个点开始,可以覆盖到第j个点,由于第二块木板覆盖初位置不定,那么我们就预处理一个a[i],表示从第[i,n]个小球开始覆盖的最优取值,用这个数组来得到第二块木板的覆盖最优值。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=2e5+5;
int t,n;
int k,x[N],y[N],a[N];
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
ios;
cin>>t;
while(t--)
{
cin>>n>>k;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++) cin>>x[i];
for(int i=1;i<=n;i++) cin>>y[i];
sort(x+1,x+1+n);
for(int i=n;i>=1;i--)//枚举第二块板子覆盖
{
int now=x[i]+k;
int ind=upper_bound(x+1,x+1+n,now)-x;
a[i]=max(a[i+1],ind-i);
}
int ans=0;
for(int i=1;i<=n;i++)//枚举第一块板子覆盖
{
int now=x[i]+k;
int ind=upper_bound(x+1,x+1+n,now)-x;
ans=max(ans,a[ind]+ind-i);
}
cout<<ans<<'\n';
}
return 0;
}
os:开始的时候想到对x数组排序,后面不知道怎么模拟木板覆盖了
C-Yet Another Array Restoration
给出排序后为等差数列中的任意两项,要求构造最大项最小的数列(SJ)。
思路:先看这两个数之间最多有多少项,不够的能放到小于较小值的就放到较小值左侧,再剩余的放到较大项右侧,注意细节,所有项都大于0!
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=55;
ll t,n,x,y;
ll a[N];
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
cin>>t;
while(t--)
{
cin>>n>>x>>y;
ll dis=y-x,d;
ll q=n-1;
while(q)
{
if(dis%q==0)
{
d=dis/q;
break;
}
q--;
}
ll num=dis/d+1;
if(num==n)
{
for(ll i=0;i<n;i++)
{
ll ans=y-i*d;
cout<<ans<<" \n"[i==n-1];
}
}
else
{
if(x-(n-num)*d>0)
{
for(ll i=0;i<n;i++)
{
ll ans=y-i*d;
cout<<ans<<" \n"[i==n-1];
}
}
else
{
if(x%d)
{
ll oth=n-x/d-num;
for(ll i=0;i<n;i++)
{
ll ans=y+d*oth-i*d;
cout<<ans<<" \n"[i==n-1];
}
}
else
{
ll oth=n-(x-1)/d-num;
for(ll i=0;i<n;i++)
{
ll ans=y+d*oth-i*d;
cout<<ans<<" \n"[i==n-1];
}
}
}
}
}
return 0;
}
D-Minimum Product
给出a,b,x,y,无论怎样操作,a均满足不小于x,b均满足不小于y,给出操作数,问a,b操作后最小的积是多少。
思路:我们知道两个数差值越大,积越小。所以在先给a减去尽可能多的值和先给b减去尽可能多的值的两个结果取较小值即可。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
int t;
ll a,b,x,y,n;
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
cin>>t;
while(t--)
{
cin>>a>>b>>x>>y>>n;
ll ans,ans1,ans2;
ans1=(b-min(n,b-y))*(a-min(a-x,n-min(n,b-y)));
ans2=(a-min(n,a-x))*(b-min(b-y,n-min(n,a-x)));
ans=min(ans1,ans2);
cout<<ans<<'\n';
}
return 0;
}
os:一开始分了很多种情况讨论,会少情况,结果最后发现这样写几行就搞定了
E-Yet Another Two Integers Problem
a最少经过几次操作得到b。
思路: 贪心。(好水啊)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=5e4+5;
int t;
ll a,b;
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
cin>>t;
while(t--)
{
cin>>a>>b;
if(a==b) cout<<"0"<<'\n';
else
{
ll minn=min(a,b);
ll maxn=max(a,b);
if((maxn-minn)%10==0)
cout<<(maxn-minn)/10<<'\n';
else
cout<<(maxn-minn)/10+1<<'\n';
}
}
return 0;
}
I - Balanced Lineup
给出一个序列,每次询问给出区间左端点和右端点,求区间内最大值和最小值的差。
思路:线段树应用。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=5e4+5;
int n,q,l,r,maxn,minn;
int a[N];
struct node
{
int maxn,minn;
} tree[N<<2];
void pushup(int i)
{
tree[i].maxn=max(tree[i<<1].maxn,tree[i<<1|1].maxn);
tree[i].minn=min(tree[i<<1].minn,tree[i<<1|1].minn);
}
void build(int i,int l,int r)
{
if(l==r)
{
tree[i].minn=tree[i].maxn=a[l];
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
pushup(i);
}
void query(int i,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
maxn=max(maxn,tree[i].maxn);
minn=min(minn,tree[i].minn);
return;
}
int mid=(l+r)>>1;
if(L<=mid) query(i<<1,l,mid,L,R);
if(R>mid) query(i<<1|1,mid+1,r,L,R);
}
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
while(q--)
{
scanf("%d%d",&l,&r);
maxn=-INF;
minn=INF;
query(1,1,n,l,r);
printf("%d\n",maxn-minn);
}
return 0;
}
M-Colorful Candies
取一段连续区间,取到不同数的最大个数是多少。
思路: 用map存每个数的个数,向map里面加一个从前面减一个。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
const int N=3e5+5;
int k,n,maxn;
ll a[N];
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
cin>>n>>k;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
map<int,int>mp;
for(int i=0;i<n;i++)
{
mp[a[i]]++;
if(i>=k-1)
{
if(maxn<mp.size()) maxn=mp.size();
mp[a[i-k+1]]--;
if(mp[a[i-k+1]]==0) mp.erase(a[i-k+1]);
}
}
cout<<maxn<<'\n';
return 0;
}
os:注意细节的处理
N-取石子游戏
思路:威佐夫博弈板子题,详细解释传送门
AC代码:
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define INF 0x3f3f3f3f
//判断是否需要开ll!!!
//判断是否需要初始化!!!
const int mod=1e9+7;
ll a,b;
int main()
{
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
while(cin>>a>>b)
{
ll maxn=max(a,b);
ll minn=min(a,b);
ll x=(ll)((sqrt(5.0)+1)/2*(maxn-minn));
if(x==minn) cout<<"0"<<'\n';
else cout<<"1"<<'\n';
}
return 0;
}
os:博弈类型见一个记一个结论,,后面想整理一个博弈的专题
图论的相关题目,,唉基础太差准备去做一下专题把板子题整清楚吧
若有错误请指教orz