【Codeforces Round #720 (Div. 2)】Codeforces-1521ABC

前半场断网,后半场疯狂wa。真·自闭场,我太菜了。

A. Nastia and Nearly Good Numbers

显然先特判B=1
构造 k 1 ∗ A ∗ B = k 2 ∗ A + k 3 ∗ A k_1*A*B=k_2*A+k_3*A k1AB=k2A+k3A
化简 k 1 ∗ B = k 2 + k 3 k_1*B=k_2+k_3 k1B=k2+k3,其中 k 2 ! = k 3 k_2!=k_3 k2!=k3 k 2 、 k 3 k_2、k_3 k2k3与B互质。
我们令 k 1 k_1 k1为1,再令 k 2 = B − 1 , k 3 = 1 k_2=B-1,k_3=1 k2=B1,k3=1。显然的,当B=2时 k 2 k_2 k2只能取 k 4 ∗ B − 1 k_4*B-1 k4B1,其中 k 4 ≥ 2 k_4\geq2 k42
构造方法还有很多。比赛的时候脑抽了,总觉得怪怪的,想再hack自己的答案。我好sb。。。

void solves(){
	ll a,b;cin>>a>>b;
	if(b>2){
		cout<<"YES\n";
		cout<<1LL*a*(b-1)<<" "<<a<<" "<<1LL*a*b<<endl;
	} else if(b==2){
		b*=2;
		cout<<"YES\n";
		cout<<1LL*a*(b-1)<<" "<<a<<" "<<1LL*a*b<<endl;
	} else{
		cout<<"NO\n";
	}
}

B. Nastia and a Good Array

一开始是想着 k ∗ m i n ( a [ i ] , a [ i − 1 ] ) − 1 k*min(a[i],a[i-1])-1 kmin(a[i],a[i1])1 m i n ( a [ i ] , a [ i − 1 ] ) min(a[i],a[i-1]) min(a[i],a[i1])互质,然后随便rand一个k。但rand的偶然性还是比较大,从左遍历到右对相邻的数进行修改的话,难免还是会影响到已经修改好的数组。
在这里插入图片描述

有一个不讲武德的解法。先找到数组中最小值的坐标,再把除掉最小值的其他n-1个数全部交替修改成两个很大的质数即可。
由于 a i ≤ 1 0 9 a_i\leq10^9 ai109 x , y ≤ 2 ∗ 1 0 9 x,y\leq2*10^9 x,y2109,那么只要任意找两个处于(1e9,2*1e9)之间的质数即可。

void solves(){
	ll pri1=1e9+7,pri2=1e9+9;
	int n;cin>>n;
	int max=1e9+1,idx=0;//数据卡得很毒,max初始化一定要>1e9
	for(int i=1;i<=n;++i){
		cin>>a[i];
		if(a[i]<max){
			max=a[i];
			idx=i;
		}
	}
	cout<<n-1<<endl;
	for(int i=1;i<=n;++i){
		if(i==idx)continue;
		if(i&1){
			a[i]=pri1;
			cout<<i<<" "<<idx<<" "<<a[i]<<" "<<a[idx]<<endl;
		} else{
			a[i]=pri2;
			cout<<i<<" "<<idx<<" "<<a[i]<<" "<<a[idx]<<endl;
		}
	}
}

C. Nastia and a Hidden Permutation

我们先确定整个数组中最大值的位置。
我们令 v a l = m a x ( m i n ( n − 1 , p i ) , m i n ( n , p j ) ) val=max(min(n-1,p_i),min(n,p_j)) val=max(min(n1,pi),min(n,pj)),当 v a l = n val=n val=n时显然有 p j = n p_j=n pj=n。特别的,当 v a l = n − 1 val=n-1 val=n1时, p i p_i pi有可能等于n,此时需要交换 p i p_i pi p j p_j pj的位置来再次确定是 p j = n − 1 p_j=n-1 pj=n1还是 p i = n p_i=n pi=n

我们可以由此在最多 ⌊ n 2 ⌋ + 1 \lfloor \frac {n} {2} \rfloor +1 2n+1次查询中寻找到最大值n的下标,设其为maxidx。
然后我们再令 v a l u e = m i n ( m a x ( 1 , p i ) , m a x ( 2 , p m a x i d x ) ) value=min(max(1,p_i),max(2,p_{maxidx})) value=min(max(1,pi),max(2,pmaxidx)),显然的, v a l u e = p i value=p_i value=pi。于是我们可以在 n − 1 n-1 n1次查询中得到剩下的排列。
理论上查询次数不会超过 ⌊ 3 n 2 ⌋ \lfloor \frac {3n} {2} \rfloor 23n

const int N=1e4+7;
int p[N];
int n;
int ask(int t,int i,int j,int x){
	cout<<"? "<<t<<" "<<i<<" "<<j<<" "<<x<<endl<<endl;
	int val;cin>>val;
	return val;
}
void solves(){
	cin>>n;
	cin.ignore();
	memset(p,0,sizeof(p));
	int idx;
	for(int i=1;i<=n;i+=2){
		if(n&1 && i==n){
			p[i]=n;idx=i;break;
		}
		int val=ask(1,i,i+1,n-1);
		if(val==n){
			p[i+1]=n;
			idx=i+1;
			break;
		}
		if(val==n-1){
			if(ask(1,i+1,i,n-1)==n){
				p[i]=n;
				idx=i;
				break;
			}
		}
	}
	for(int i=1;i<=n;++i){
		if(i==idx)continue;
		int val=ask(2,i,idx,1);
		p[i]=val;
	}
	cout<<"! ";
	for(int i=1;i<=n;++i)cout<<p[i]<<" ";cout<<endl<<endl;
}
int main(){
//	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int OwO=1;
	cin>>OwO;
	cin.ignore();
	while(OwO--){
		solves();
	}
}
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值