题解 P5032 【经验】
解法1:
我有信仰,我是MC玩家,输出-1。预计得分:15.
解法2:
我会特判,处理ai=1,n=1的情况,预计得分:15.
解法3:
我会暴力,直接模拟。时间复杂度
解法4:
我们发现,每次只要合并最小的两本书,然后合并。再往上找。找最小的两本书可以类似于合并果子,用优先队列做就好啦。预计得分:40-95(数据居然没有卡掉,还是那个-1的点卡常卡掉的23333).
解法5:
我们继续寻找规律,或者由合并果子的思路得来。这些附魔书合并前和合并后均有单调性,我们开两个队列就可以
解法6:
由于是两本合成一本附魔书,所以最坏情况下,附魔书的最大等级为
在这里附上50分代码和100分代码:
50pts:
#include<bits/stdc++.h>
using namespace std;
struct Node{
int cost,lev,lei;
friend bool operator < (Node x,Node y){
if(x.lev==y.lev){
if(x.cost==y.cost) return x.lei>y.lei;
return x.cost>y.cost;
}
return x.lev>y.lev;
}
}x;
priority_queue <Node> q;
int ans=0,cnt=214748347;
int ex_gcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return a;
}
int e=ex_gcd(b,a%b,y,x);
y-=x*(a/b);
return e;
}
int main(){
int n,qwq,orz;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&x.lev),x.lei=1,x.cost=0,q.push(x);
Node fir;
while(q.size()>1){
if(q.top().lev>ans) ans=q.top().lev,cnt=q.top().cost;
else if(q.top().lev==ans) cnt=min(cnt,q.top().cost);
fir=q.top(); q.pop();
while(q.top().lev!=fir.lev) fir=q.top(),q.pop();
Node nxt,sec=q.top();
nxt.cost=fir.cost+sec.cost+fir.lei+sec.lei;
nxt.lei=max(fir.lei,sec.lei)*2+1;
nxt.lev=fir.lev+1;
q.pop(); q.push(nxt);
}
if(q.top().lev>ans) ans=q.top().lev,cnt=q.top().cost;
if(ex_gcd(ans,cnt,qwq,orz)!=1) cout<<-1<<endl;
else{
qwq=(qwq%cnt+cnt)%cnt;
cout<<qwq<<endl;
}
return 0;
}
100pts:
#include<queue>
#include<cstdio>
#include<iostream>
#define int long long
#define MAXN 10000200
using namespace std;
int c[MAXN+50],d[MAXN+50],cnt,ans;
int ex_gcd(int a,int b,int &x,int &y){
if(b==0){
x=1,y=0;
return a;
}
int e=ex_gcd(b,a%b,y,x);
y-=x*(a/b);
return e;
}
int dg(int x){//获得一本等级为x的书的花费
if(d[x]){
d[x]--;
return 1;
}
int p=dg(x-1),q=dg(x-1);
ans+=p+q;
return (max(p,q)*2+1) ;
}
inline void read(int &x){
char ch;x=0;
while(!isdigit(x)) ch=getchar();
while(isdigit(x)) x=x*10+ch-'0',ch=getchar();
}
signed main(){
// freopen("exp.in","r",stdin);
// freopen("exp.out","w",stdout);
int n,x,y;
cin>>n;//cout<<"qwq"<<endl;
for(int i=1;i<=n;i++){
scanf("%lld",&x);
d[x]++;c[x]++;
}//cout<<"qwq"<<endl;
for(int i=1;i<=MAXN;i++){
c[i+1]+=c[i]/2; c[i]%=2;
if(c[i+1]) cnt=max(cnt,i+1);
} //cout<<"qwq"<<endl;
dg(cnt);
if(ex_gcd(cnt,ans,x,y)!=1) cout<<-1<<endl;
else{
x=(x%ans+ans)%ans;
printf("%lld\n",x);
}
// cout<<ans<<" "<<cnt<<endl;
return 0;
}