\(\sf B-Insurance\)
题目
解法
感觉自己的做法还蛮特别的,就来写一写。虽然并不优。
首先将算式转化成:
我们发现,后面 \(\max\) 的取值和 \(2x\) 与 \(A_i\) 的关系有关,于是我们排个序枚举分界点,这样前一半是 \(x-A_i\) 后一半是 \(-x\) 就可以快速计算了。
最后再判断一下取 \(A_{i}/2\) 和 \(A_{i+1}/2\) 哪个结果小就行了。
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
#define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
template <typename T> void Out(T x) {cerr<<x<<"\n";}
template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
const int maxn=1e5+5;
int n;
double a[maxn],sum,ans;
int main() {
n=read(9);
rep(i,1,n) a[i]=read(9);
sort(a+1,a+n+1);
rep(i,1,n+1) {
double x,tmp=i-1-(n-i+1);
if(tmp>0) x=a[i-1]/2;
else x=a[i]/2;
ans=Min(ans,tmp*x-sum);
sum+=a[i];
}
printf("%.10f\n",(ans+sum)/n);
return 0;
}
\(\sf C-Calculator\)
题目
解法
手玩就能发现,这其实就是将 \(n\) 拆分成几个斐波那契数。
可以证明,任意正整数 \(n\) 可以被拆分成互异的斐波那契数。又因为如果选择了 \(\text{fib}_i,\text{fib}_{i+1}\) 肯定就会换成 \(\text{fib}_{i+2}\),所以我们不会选择连续的斐波那契数。而数据范围中斐波那契数最多到 \(87\) 项(\(\text{fib}_1=\text{fib}_{2}=1\)),所以如果我们都选奇数项就有 \(44\) 项。不过事实上这个上界达不到,因为 \(\text{fib}_{87}+\text{fib}_{85}+\text{fib}_{83}>10^{18}\)。
构造就是边加入 \(1\),边用 \(3,4\) 操作拓展斐波那契数列,\(3,4\) 操作的上界是 \(86\)。
所以总体上界为 \(130\),足以通过此题。
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
#define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
template <typename T> void Out(T x) {cerr<<x<<"\n";}
template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
typedef long long ll;
ll n,f[100];
int sta[100],tp,ans[200],len,fuck;
void init() {
f[1]=f[2]=1;
rep(i,3,90) f[i]=f[i-1]+f[i-2];
}
int main() {
init();
n=read(9ll);
fep(i,90,1) if(n>=f[i]) sta[++tp]=i,n-=f[i];
fep(i,tp,1)
if(sta[i]&1) {
while(fuck<sta[i]-1) {
if(fuck&1) ans[++len]=4;
else ans[++len]=3;
++fuck;
}
ans[++len]=1;
}
else {
while(fuck<sta[i]-1) {
if(fuck&1) ans[++len]=4;
else ans[++len]=3;
++fuck;
}
ans[++len]=2;
}
print(len,'\n');
fep(i,len,1) print(ans[i],'\n');
return 0;
}
\(\sf E-Increasing\ LCMs\)
题目
解法
我们考虑 \(a_n\) 满足的条件:将所有数质因数分解,\(a_n\) 分解后某质数 \(p\) 的幂次大于 \([1,n-1]\) 中任意一个数 \(p\) 的幂次。
那我们每次找到可以作为末尾的数,然后从后往前填。
考虑贪心的正确性。首先肯定是越填限制越松的。对于同一状态下都可以填的两个数 \(i,j\),显然使它们可以作为末尾的质因子互异,所以它们的先后顺序是可以随便定的。
代码
#include <bits/stdc++.h>
using namespace std;
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
#define debug(...) do {cerr<<__LINE__<<" : ("#__VA_ARGS__<<") = "; Out(__VA_ARGS__); cerr<<flush;} while(0)
template <typename T> void Out(T x) {cerr<<x<<"\n";}
template <typename T,typename ...I> void Out(T x,I ...NEXT) {cerr<<x<<", "; Out(NEXT...);}
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
typedef long long ll;
const int maxn=105;
int n,id[maxn];
ll a[maxn],g[maxn][maxn];
int main() {
n=read(9);
rep(i,1,n) a[i]=read(9ll),id[i]=i;
rep(i,1,n) rep(j,1,n) g[i][j]=gcd(a[i],a[j]);
fep(i,n,1) {
bool flag=false;
rep(j,1,i) {
ll tmp=1;
rep(k,1,i) if(j^k) tmp=lcm(tmp,g[id[j]][id[k]]);
if(tmp^a[id[j]]) {
rep(k,j,i-1) swap(id[k],id[k+1]);
flag=true; break;
}
}
if(!flag) return puts("No"),0;
}
puts("Yes");
rep(i,1,n) print(a[id[i]],' '); puts("");
return 0;
}