解题报告CF DIV2 #ROUND 723 A~D
Posted 鱼竿钓鱼干
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题报告CF DIV2 #ROUND 723 A~D相关的知识,希望对你有一定的参考价值。
【解题报告】CF DIV2 #ROUND 723 A~D
比赛评价:
发现这场十点就开了,然后就和ph巨佬一起玩了一场。我两分别再A和B罚时罚飞了,索性后面把C1,C2整出来了
排名2500+,而且极其刺激,最后3分钟找出C1错误,最后30S交了C1,C2。爽到飞起
A. Mean Inequality
题意
2*n个数成环,找到一个排列使得任意位置满足
2
∗
b
i
!
=
b
i
−
1
+
b
i
+
1
2*b_i!=b_{i-1}+b_{i+1}
2∗bi!=bi−1+bi+1
思路
先排序,然后
结果我憨憨的写sort只写了前n个,WA掉一发呜呜呜
代码
// Problem: A. Mean Inequality
// Contest: Codeforces - Codeforces Round #723 (Div. 2)
// URL: https://codeforces.com/contest/1526/problem/A
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// FishingRod
#include<bits/stdc++.h>
using namespace std;
#define endl "\\n"
typedef long long LL;
typedef pair<int,int> PII;
#define MULINPUT
/*DATA & KEY
*/
int T;
const int N=55;
LL a[N],b[N];
void solve(int C)
{
//NEW DATA CLEAN
//NOTE!!!
int n;cin>>n;
for(int i=1;i<=2*n;i++)cin>>a[i];
sort(a+1,a+1+2*n);
for(int i=1,j=1;i<=n;i++,j+=2)b[j]=a[i];
for(int i=2*n,j=2;i>=n+1;i--,j+=2)b[j]=a[i];
for(int i=1;i<=2*n;i++)cout<<b[i]<<" ";
puts("");
}
int main()
{
#ifdef MULINPUT
scanf("%d",&T);
for(int i=1;i<=T;i++)solve(i);
#else
solve(1);
#endif
return 0;
}
B. I Hate 1111
题意
问一个数能不能由11,111,1111……构造出来
思路
可以发现1111,11111……都可以由11,111构造出来,所以只需要考虑能否被11和111构造出来。
也就是
C
=
x
∗
11
+
y
∗
111
C=x*11+y*111
C=x∗11+y∗111,要有非负整数解
有定理:可以看一下这题 小凯的疑惑
如
果
a
,
b
均
是
正
整
数
且
互
质
,
那
么
由
a
x
+
b
y
,
x
≥
0
,
y
≥
0
不
能
凑
出
的
最
大
数
是
a
b
−
a
−
b
如果 a,b均是正整数且互质,那么由 ax+by,x≥0,y≥0不能凑出的最大数是 ab−a−b
如果a,b均是正整数且互质,那么由ax+by,x≥0,y≥0不能凑出的最大数是ab−a−b
也就是最大不能凑出1,099。
然后直接枚举一波<1099能凑出的数即可
代码
#include<bits/stdc++.h>
using namespace std;
map<int,bool>mp;
int main(){
int n;cin>>n;
for(int i=0;i<=100;i++)
for(int j=0;j<=10;j++)
mp[i*11+j*111]=1;
for(int i=1;i<=n;i++){
int x;cin>>x;
if(x>1099||mp[x])puts("YES");
else puts("NO");
}
return 0;
}
大佬的奇妙数论操作
// Problem: B. I Hate 1111
// Contest: Codeforces - Codeforces Round #723 (Div. 2)
// URL: https://codeforces.com/contest/1526/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// FishingRod
#include<bits/stdc++.h>
using namespace std;
#define endl "\\n"
typedef long long LL;
typedef pair<int,int> PII;
#define MULINPUT
/*DATA & KEY
*/
int T;
void solve(int C)
{
//NEW DATA CLEAN
//NOTE!!!
LL x;cin>>x;
if(x%11<=x/11/10)puts("YES");
else puts("NO");
}
int main()
{
#ifdef MULINPUT
scanf("%d",&T);
for(int i=1;i<=T;i++)solve(i);
#else
solve(1);
#endif
return 0;
}
C1+C2 Potions
题意
有n瓶药水,对应值a[i],a[i]可正可负,范围正负1e9,对于每瓶药水你可以选择喝或者不喝,但是必须保证选择药水的和非负,问最多喝多少瓶。
思路
C1和C2只是n数据量不同,我直接写通解了。
主要是反悔贪心和单调队列的思想,个人是用优先队列实现的。
反悔贪心看一看这一篇文章
首先有一个显然的贪心思想就是,只要sum不会0,那就喝下药水但是这样其实是不ok的。
10 -10 -1 -2 -3
显然我们可以选择不喝-10,喝后面3瓶。那么,如何实现这一操作呢。
答案是反悔贪心。
反悔贪心主要的思想是替换和做差。
首先我们一直喝,直到继续喝下去sum可能<0。
然后我们就要思考当前x能否替换掉先前喝过的值最小的药水。
替换的条件有以下2个
①替换后sum>=0
②x比替换的值大
也就是if(sum-heap.top()+x>=0&&heap.top()<x)
代码
// Problem: C1. Potions (Easy Version)
// Contest: Codeforces - Codeforces Round #723 (Div. 2)
// URL: https://codeforces.com/contest/1526/problem/C1
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// FishingRod
#include<bits/stdc++.h>
using namespace std;
#define endl "\\n"
typedef long long LL;
typedef pair<int,int> PII;
//#define MULINPUT
/*DATA & KEY
*/
int T;
void solve(int C)
{
//NEW DATA CLEAN
priority_queue<LL,vector<LL>,greater<LL>>heap;
//NOTE!!!
int n;scanf("%d",&n);
LL sum=0;
for(int i=1;i<=n;i++)
{
LL x;scanf("%lld",&x);
if(heap.empty())//如果空
{
if(x>=0)//正的直接加入
{
heap.push(x);
sum+=x;
}
}
else
{
if(x>=0)//正的直接加入
{
heap.push(x);
sum+=x;
}
else//x<0
{
if(sum+x>=0)//可以喝直接加入
{
sum+=x;
heap.push(x);
}
else
{
if(sum-heap.top()+x>=0&&heap.top()<x)//满足替换条件,我们就把堆顶的药水换掉
{
sum=sum-heap.top()+x;
heap.pop();
heap.push(x);
}
}
}
}
}
cout<<heap.size()<<endl;
}
int main()
{
#ifdef MULINPUT
scanf("%d",&T);
for(int i=1;i<=T;i++)solve(i);
#else
solve(1);
#endif
return 0;
}
D.Kill Anton
题意
给你一个字符串,你要对它的字母重新排列。排列后的字符串只能通过相邻位置两两交换的方式回到原串。请你构造一个排列方式,使得它变回原串的操作次数最多。
思路
相邻交换的话,联想到冒泡排序和逆序对数量,每交换一次逆序对增加一次,也就是说让映射过去的逆序对数最多
emmm然后蒟蒻鱼竿就卡在这里了。
问了大佬,大佬说有个奇妙的结论:相同字母一定是连续的
然后直接枚举
4
!
4!
4!种排列可能,求逆序对,记录最大的字符串即可。
代码
// Problem: D. Kill Anton
// Contest: Codeforces - Codeforces Round #723 (Div. 2)
// URL: https://codeforces.com/contest/1526/problem/D
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// FishingRod
#include<bits/stdc++.h>
using namespace std;
#define endl "\\n"
typedef long long LL;
typedef pair<int,int> PII;
#define MULINPUT
/*DATA & KEY
*/
int T;
const int N=2E5+10;
int num[N],sort_tmp[N];
int get_id(char c)//获取对应id
{
if(c=='A')return 0;
if(c=='N')return 1;
if(c=='T')return 2;
if(c=='O')return 3;
}
LL merge_sort(int l,int r)//归并求逆序对
{
if(l>=r)return 0;
int mid=l+r>>1;
LL res=merge_sort(l,mid)+merge_sort(mid+1,r);
int k=0,i=l,j=mid+1;//i是l别打成1
while(i<=mid&&j<=r)
{
if(num[i]<=num[j])sort_tmp[k++]=num[i++];
else
{
sort_tmp[k++]=num[j++];
res+=mid-i+1;//q[i]>q[j],左区间剩下的所有数与右区间当前数成为逆序对
}
}
while(i<=mid)sort_tmp[k++]=num[i++]; //扫尾
while(j<=r)sort_tmp[k++]=num[j++];
for(int i=l,j=0;i<=r;i++,j++)num[i]=sort_tmp[j];//不要写成i=1
return res;
}
LL get_rev(string s,int* p){//求字符串逆序对数量
int len=s.length();
for(int i=0;i<len;i++)
for(int j=0;j<4;j++)
if(get_id(s[i])==p[j])//根据排序比较规则p[j],把string映射成数组求逆序对
{
num[i]=j;//下标j就是rank
break;
}
return merge_sort(0,len-1);
}
void solve(int C)
{
//NEW DATA CLEAN
//NOTE!!!
int p[]={0,1,2,3};//排列顺序,同时也是求逆序对数的排序比较规则
string s;cin>>s;
string ans,A,N,T,O;
for(int i=0;s[i];i++)
{
if(s[i]=='A')A+='A';
if(s[i]=='N')N+='N';
if(s[i]=='T')T+='T';
if(s[i]=='O')O+='O';
}
LL rev=0;
do{
string tmp;
for(int i=0;i<4;i++){
if(p[i]==0)tmp+=A;
if(p[i]==1)tmp+=N;
if(p[i]==2)tmp+=T;
if(p[i]==3)tmp+=O;
}
LL k=get_rev(s,p);
if(k>=rev)
{
rev=k;
ans=tmp;
}
}while(next_permutation(p,p+4));
cout<<ans<<endl;
}
int main()
{
#ifdef MULINPUT
scanf("%d",&T);
for(int i=1;i<=T;i++)solve(i);
#else
solve(1);
#endif
return 0;
}
反思
A:
对于成环的,使用sort或者其他东西的时候一定要注意2n而不是n
B:
问能否用给
以上是关于解题报告CF DIV2 #ROUND 723 A~D的主要内容,如果未能解决你的问题,请参考以下文章
CF Round #600 (Div 2) 解题报告(A~E)
Codeforces Round #599 Div2解题报告A-D