(sf B-Insurance)
题目
解法
感觉自己的做法还蛮特别的,就来写一写。虽然并不优。
首先将算式转化成:
[sum_{i=1}^n A_i+minleft { sum_{i=1}^n max{x-A_i,-x}
ight }
]
我们发现,后面 (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<<"
";}
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
",(ans+sum)/n);
return 0;
}
(sf C-Calculator)
题目
解法
手玩就能发现,这其实就是将 (n) 拆分成几个斐波那契数。
可以证明,任意正整数 (n) 可以被拆分成互异的斐波那契数。又因为如果选择了 ( ext{fib}_i, ext{fib}_{i+1}) 肯定就会换成 ( ext{fib}_{i+2}),所以我们不会选择连续的斐波那契数。而数据范围中斐波那契数最多到 (87) 项(( ext{fib}_1= ext{fib}_{2}=1)),所以如果我们都选奇数项就有 (44) 项。不过事实上这个上界达不到,因为 ( ext{fib}_{87}+ ext{fib}_{85}+ ext{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<<"
";}
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,'
');
fep(i,len,1) print(ans[i],'
');
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<<"
";}
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;
}