嘛,为毛现在比赛都这么晚…
所以我就去看俺妹了…结果看到三点…比打比赛还晚诶…
嘛…虽然看过动画但再看小说依旧虐的不行…看到黑猫本子上的”和先辈分手”,整个人就不好了,于是睡到了11:30…
好吧,下面是题解:
A
题目大意:
求在[l,r]内k的幂的个数
题解:
这是个cha的好题,数据范围给了好大…
rank前几的都是几十Hack
代码:
#include <bits/stdc++.h>
using namespace std;
long long l,r,k,pow=1;
int cnt=0;
long long ans[100];
int main(){
cin>>l>>r>>k;
while(pow<=r){
if(pow>=l) ans[cnt++]=pow;
if((double)pow*k<=r) pow*=k; else break;
}
if(!cnt) puts("-1");
else for(int i=0;i<cnt;i++) cout<<ans[i]<<' ';
return 0;
}
B
题目大意:
给你一些形如10…0的数,和最多一个的其他数,求他们的乘积(product)
题解:
记录下特殊的数和0的个数
代码:
#include <bits/stdc++.h>
using namespace std;
string s,ss="1";
int n,zero=0;
bool flag=0;
int main(){
cin>>n;
while(n--){
cin>>s;
if(s.length()==1 && s[0]=='0'){
puts("0");
return 0;
}
bool ok=s[0]=='1';
for(int i=1;i<s.length();i++)
if(s[i]!='0'){
ok=0;
break;
}
if(ok) zero+=s.length()-1; else ss=s;
}
cout<<ss;
while(zero--) cout<<0;
return 0;
}
C
题目大意:
给出一个点P和一个多边形,求以P为圆心的圆环在包含整个多边形时的最小面积
题解:
我们只需求出每个点到P的距离d,答案就是PI*(maxd^2-mind^2),然后你就错了…
因为有些时候圆会在内部先与边切上再与点相交
怎么办呢?
由于点是顺时针给出的,只需依次计算p到线段的距离更新mind,p到端点的距离更新maxd
注意数据范围…
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN=int(1e5+5);
const double PI=acos(-1);
int n;
struct Point{
int x,y; double d;
Point(){}
Point(int x,int y);
}p,a[MAXN];
double Sqr(double x){return x*x;}
double Dis(Point A,Point B){return Sqrt(Sqr(A.x-B.x)+Sqr(A.y-B.y));}
long long Det(Point A,Point B,Point C){return 1ll*A.x*B.y+1ll*B.x*C.y+1ll*C.x*A.y-1ll*A.y*B.x-1ll*B.y*C.x-1ll*C.y*A.x;}
Point::Point(int x,int y):x(x),y(y){d=Dis(*this,p);}
int main(){
cin>>n;
cin>>p.x>>p.y;
int x,y;
for(int i=0;i<n;i++){
cin>>x>>y;
a[i]=Point(x,y);
}
double l,_min=1e18,_max=0;
for(int i=0;i<n;i++){
_min=min(_min,a[i].d);
_max=max(_max,a[i].d);
l=Dis(a[i],a[(i+1)%n]);
if(Sqr(l)+Sqr(a[i].d)>Sqr(a[(i+1)%n].d) && Sqr(l)+Sqr(a[(i+1)%n].d)>Sqr(a[i].d)){
_min=min(_min,abs((double)Det(a[i],p,a[(i+1)%n]))/l);
}
}
printf("%.9f\n",PI*(Sqr(_max)-Sqr(_min)));
return 0;
}
D
题目大意:
给你一个数列(元素大小上限为A),一个数m,参数cf和cm,将不超过m加到数列上,使得force=达到上限的元素的个数*cf+最小的元素值*cm最大
题解:
先将数列排序
从大到小依次将数据变为A,然后每次对最小值进行二分,计算出force进行更新
代码:
#include <bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=0;i<n;i++)
typedef long long LL;
const int MAXN=int(1e5+5);
int n,A,cf,cm;
int a[MAXN],tmp1[MAXN],tmp2[MAXN];
LL s[MAXN],m;
bool cmp(int x,int y){return a[x]<a[y];}
int main(){
cin>>n>>A>>cf>>cm>>m;
For(i,n) tmp1[i]=i,cin>>a[i];
if(!cm && !cf){//坑爹的情况,在force不变时不对数列进行变化
puts("0");
For(i,n) cout<<a[i]<<' ';
return 0;
}
sort(tmp1,tmp1+n,cmp);
sort(a,a+n);
For(i,n){
s[i]=a[i];
i?s[i]+=s[i-1]:0;
}
LL ret,ans=0;
a[n]=A;//特殊情况,即使把所有的m都加到最大数上也不够A
int _max=0,_min=int(1e9);//_max:A的个数,_min:最小值
for(int i=n;i>=0;i--){//将i..n-1都变为A
ret=m-(1ll*A*(n-i)-(s[n-1]-(i?s[i-1]:0)));
if(ret<0) break;
if(!cm){//cm==0时不改动最小值
ans=1ll*(n-i)*cf;
_max=n-i; _min=0;
continue;
}
LL l=a[0],r=A,mid;//二分最小值
while(l<r){
mid=r-((r-l)>>1);
int k=upper_bound(a,a+n,mid)-a;
k=min(k,i);
if(ret>=1ll*k*mid-(k?s[k-1]:0)) l=mid; else r=mid-1;
}
LL force=1ll*(n-i)*cf+1ll*l*cm;
if(force>ans){
ans=force;
_max=n-i; _min=l;
}
}
cout<<ans<<endl;
For(i,n-_max) tmp2[tmp1[i]]=max(_min,a[i]);
for(int i=n-_max;i<n;i++) tmp2[tmp1[i]]=A;
For(i,n) cout<<tmp2[i]<<' ';
return 0;
}
E
题目大意:
给你一些元素,问将他们排成环后,从两个相邻的元素间断开,是否能形成回文串,能的话最多有几种断开方法
题解
计算出现次数为奇数的元素个数odd
若odd>=2,无解
对于其他情况可以对元素进行分组,分成g=gcd(a[i])组,则每组都可构成一个回文串,自然就有g种断开方法,具体看例子吧
e.g.
输入:
3
6 12 6
构造:
分成6组,每组为abbc或cbba
则可构成 abbc cbba abbc cbba abbc cbba
每组后断开就是6种方法输入:
3
6 9 6
构造:
分成三组,每组为abcbcba
则可构成 abcbcba abcbcba abcbcba
每组后断开就是3种方法
代码:
#include <bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=0;i<n;i++)
const int MAXN=26;
int n;
int a[MAXN],m=0,odd=0;
char s[int(1e5+5)];
int main(){
cin>>n;
For(i,n)
cin>>a[i],m+=a[i],odd+=a[i]&1;
if(n==1){
cout<<m<<endl;
For(i,m) putchar('a');
return 0;
}
if(odd>=2){
puts("0");
For(i,n)
For(j,a[i])
putchar('a'+i);
return 0;
}
int g=a[0];
For(i,n) g=__gcd(g,a[i]);
printf("%d\n",g);
int idx=0,nodd=-1;
For(i,n){
a[i]/=g;
if(g&1){
if(a[i]&1) a[i]=(a[i]-1)>>1,nodd=i;
else a[i]>>=1;
}
}
For(i,n)
For(j,a[i])
s[idx++]='a'+i;
int k=idx;
if(nodd!=-1) s[idx++]='a'+nodd;
For(i,k)
s[idx++]=s[k-i-1];
for(int i=idx;i<m;i++)
s[i]=s[i-idx];
puts(s);
return 0;
}