[ARC 122]

Posted fhq_treap

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ARC 122]相关的知识,希望对你有一定的参考价值。

最近状态差到爆炸.
\\(AT\\)连掉两把分,啥时候能上黄啊。

\\(A\\)
考虑直接动归。
\\(O(n^2)\\)的动归后缀和优化成\\(O(n)\\)

A
#include<iostream>
#include<cstdio>
#define ll long long
#define N 100005
#define mod 1000000007

ll a[N],f[N],g[N],sf[N],sg[N];
ll n,ans,sum;

int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i)
	scanf("%lld",&a[i]),sum = (sum + a[i]) % mod;
	//f:i为-时从i到n有多少种合法方案,g:这些合法方案的权数。
	f[n] = 1,g[n] = (-2 * a[n] + mod) % mod;
	f[n + 1] = 1;
	sf[n] = 2,sf[n + 1] = 1,sg[n] = g[n];
	for(int i = n - 1;i >= 2;--i){
		f[i] = sf[i + 2];
		g[i] = (f[i] * (-2 * a[i] + mod) % mod + sg[i + 2]) % mod;
		sf[i] = (sf[i + 1] + f[i]) % mod;
		sg[i] = (sg[i + 1] + g[i]) % mod; 
	}
//	for(int i = n;i >= 2;--i)
//	std::cout<<f[i]<<" "<<g[i]<<std::endl;
	for(int i = n;i >= 2;--i)
	ans = (ans + sum * f[i] % mod + g[i]) % mod;
	ans = (ans + sum) % mod;
	std::cout<<ans<<std::endl;
}

\\(B\\)
听说B是一个结论题,正解来看呢,应该是把\\(n\\)个可取值都试一遍,但是我写的模拟退火。

B
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#define ll long long
#define N 100005

struct P{int x,y,w;}p[N];

ll n;

double ansx,ansy;

inline  double find(double x){
	double ans = 0;
	for(int i = 1;i <= n;++i)
	ans += (p[i].x + x - std::min((double)p[i].x,(double)(2 * x))) / (1.0 * n);
	return ans;
}

int main(){
//	freopen("q.in","r",stdin);
//	freopen("q.out","w",stdout);
	srand(273352);
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i){
		scanf("%d",&p[i].x);
		ansx += p[i].x;	}
	ansx = (ansx) / (1.0 * n);
	ansy = 0x7f7f7f7f;
	double eps = 1e-15;
	double T = 200;//初始温度 
	while(T > eps && ((double)(clock())/CLOCKS_PER_SEC)<1.9){//终止态 
//		std::cout<<T<<" "<<(rand() * 2 - RAND_MAX) * T<<std::endl;
		double nowx = ansx + ((rand() * 2 - RAND_MAX + 1) * T);//在值域[ansx - t,ansx + t];中挑选一个随机数
		long double z = find(nowx) - find(ansx);
		if(z < 0)
		ansx = nowx,ansy = std::min(ansy,find(nowx));
		else
		if(exp(-z / T) * RAND_MAX > rand())//随机接受 
		ansx = nowx;
		T *= 0.997;//降温速率 
//		std::cout<<ansx<<std::endl;
	}
	printf("%.12lf\\n",ansy);
}

\\(C\\)
考虑每一个数在\\(fib\\)数系下都有唯一分解。
做完了。

C
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long

ll f[200],to[200],ti[200];
ll ans[200];

ll n;
ll k;

//0 1
//1 1
//1 2
//1 3
//4 3
//4 7

int main(){
	scanf("%lld",&n);
	ll q = n;
	ll len = 1;
	f[0] = 1,f[1] = 1;
	while(f[len] <= n + 1){
		f[++len] = f[len - 1] + f[len - 2];
	}
	for(int i = len;i >= 1;--i)
	if(n >= f[i])
	to[++to[0]] = i,n -= f[i];
	std::sort(to + 1,to + to[0] + 1);
	for(int i = 1;i <= to[0];++i)
	ti[i] = to[to[0]] - to[i];
	std::sort(ti + 1,ti + to[0] + 1);
	ll s = to[to[0]];
	ll x = 0,y = 0;
	ll now = 1;
	for(int i = 0;i <= s;++i){
		if(i == ti[now]){
			if(i & 1)
			ans[++k] = 1,x += 1;
			else
			ans[++k] = 2,y += 1;
			++now;
		}
		if(i & 1)
		ans[++k] = 4,y += x;
		else
		ans[++k] = 3,x += y;
	}
	std::cout<<k<<std::endl;
	if(x == q){
		for(int i = 1;i <= k;++i)
		std::cout<<ans[i]<<std::endl;
	}
	else{
		for(int i = 1;i <= k;++i){
			if(ans[i] <= 2)
			std::cout<<3 - ans[i]<<std::endl;
			else
			std::cout<<7 - ans[i]<<std::endl;
		}
	}
} 

\\(D\\)
考虑如果后手已经想好的每个数对,那么其实游戏进程没有差别。
所以这是一个假博弈。
我们考虑对每一位进行操作,如果这一位的\\(0\\),\\(1\\)的数量都是偶数,那么递归进子树操作。
否则则把左子树和右子树左右匹配,用\\(01tire\\)找出最小的匹配,因为再往下递归的所有对都小于这个匹配。

D
#include<iostream>
#include<cstdio>
#define ll long long

ll to[12000005][2];
ll cnt[12000005];

ll n;

ll dfncnt;

inline void insert(ll x){
	ll u = 0;
	cnt[u] ++ ;
	for(int i = 29;i >= 0;--i){
		int t = (x >> i) & 1;
		if(!to[u][t])
		to[u][t] = ++ dfncnt;
		u = to[u][t];
		cnt[u] ++ ;
	}
} 
 
ll ans = 0,tmp;

#define l(u) to[u][0]
#define r(u) to[u][1]

inline void find(ll p1,ll p2,ll now,ll dep){
//	std::cout<<p1<<" "<<p2<<" "<<now<<" "<<dep<<std::endl;
	if(dep == 0){
		tmp = std::min(now,tmp);
		return;
	}
	bool q = 0;
	for(int i = 0;i <= 1;++i)
	if(to[p1][i] && to[p2][i]){
		q = 1;
		find(to[p1][i],to[p2][i],now,dep - 1);
	}
	if(q)
	return;
	for(int i = 0;i <= 1;++i)
	if(to[p1][i] && to[p2][!i]){
		find(to[p1][i],to[p2][!i],now | (1 << (dep - 1)),dep - 1);
		q = true;
	}
}

inline void dfs(int u,int dep){
//	std::cout<<u<<" "<<dep<<std::endl;
	if(!to[u][1] && !to[u][0])
	return;
	if(cnt[l(u)] % 2 && cnt[r(u)]){
		tmp = (1 << 30);
		find(l(u),r(u),(1 << (dep - 1)),dep - 1);
		ans = std::max(ans,tmp);
		return ;
	}
	if(l(u))
	dfs(l(u),dep - 1);
	if(r(u))
	dfs(r(u),dep - 1);
}

int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= 2 * n;++i){
		ll x;
		scanf("%lld",&x);
		insert(x);
	}
	dfs(0,30);
	std::cout<<ans<<std::endl;
}

以上是关于[ARC 122]的主要内容,如果未能解决你的问题,请参考以下文章

ARC122A Many Formulae 题解

[ARC122E]Increasing LCMs

[ARC 122]

[ARC122C] Calculator

[ARC122D]XOR Game

[ARC122D]XOR Game