\(\sf B-Insurance\)

题目

传送门

解法

感觉自己的做法还蛮特别的,就来写一写。虽然并不优。

首先将算式转化成:

\[\sum_{i=1}^n A_i+\min\left \{ \sum_{i=1}^n \max\{x-A_i,-x\} \right \} \]

我们发现,后面 \(\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;
}
posted on 2021-06-17 17:37  Oxide  阅读(87)  评论(0编辑  收藏  举报