【Codeforces Round #716 (Div. 2)】Codeforces-1514ABC

A. Perfectly Imperfect Array

多个完全平方数的乘积也是完全平方数。如要找到一个非空子序列的乘积不是完全平方数的话,只要原序列中存在非完全平方数即可。

void solves(){
	int n,po;cin>>n;
	int flag=0;
	while(n--){
		cin>>po;
		int i=(int)sqrt(po);
		if(i*i!=po) flag=1;
	}
	cout<<(!flag ? "NO":"YES")<<endl;
}

B. AND 0, Sum Big

1.数组中元素不大于 2 k − 1 2^k-1 2k1,即每个元素在二进制中最大为k位;
2.要满足所有元素按位&运算为0,即数组中每个元素化为二进制对齐后,每个位数至少有一个0。说的可能有点抽象,举个例子:
在n=3,k=5时,在不考虑【元素和尽量大】这一条件的时候,可能满足按位&=0的数组有:
a[0]=0 1 1 0 1 ( 2 ) _{(2)} (2)
a[1]=1 0 0 1 0 ( 2 ) _{(2)} (2)
a[2]=0 1 1 0 1 ( 2 ) _{(2)} (2)
即化为二进制对齐后,每列至少存在一个0
3.要满足数组元素和尽量大,则要满足每列的1尽可能多。则只需要每列存在一个0时满足题意。此时数组元素和为 ( 2 k − 1 ) ∗ ( n − 1 ) (2^k-1)*(n-1) (2k1)(n1)
如例子:
在n=3,k=5时:
a[0]=1 1 1 0 1 ( 2 ) _{(2)} (2)
a[1]=1 0 0 1 0 ( 2 ) _{(2)} (2)
a[2]=0 1 1 1 1 ( 2 ) _{(2)} (2)
4.分析完题意所给的条件后,我们知道,0在每一列中有n种放置情况,共有k列。即答案为 n k n^k nk。由于n的范围到了1e5,可用快速幂水一下。

ll qpow(ll b,ll p){
	ll r=1;
	while(p){
		if(p&1) r=(r*b)%mod;
		b=(b*b)%mod;
		p/=2;
	}
	return r%mod;
}
void solves(){
	int n,k;cin>>n>>k;
	cout<<qpow(n,k)<<endl;
}

C. Product 1 Modulo N

首先我们记 a n a_n an为数列[1,2,…n-1]。
再记所求为 A = ∏ i = 1 k a k i A=\prod_{i=1}^ka_{k_i} A=i=1kaki 其中k为最长子序列的长度, k i k_i ki为原序列下标。
要满足A%n=1,则分以下两种情况讨论:
1.当A<n时,A=1,此时k=1.
2.当A>n时,由辗转相除法易得A与n的最大公约数为1,即A与n互质,即A与n没有相同的质因子。由于 A = ∏ i = 1 k a k i A=\prod_{i=1}^ka_{k_i} A=i=1kaki,所以n与 a k i a_{k_i} aki互质。
此时我们再把 a n a_n an中所有与n互质的元素累乘,记为 B = ∏ i = 1 q a q i B=\prod_{i=1}^qa_{q_i} B=i=1qaqi,其中 q i q_i qi为与n互质的 a i a_i ai下标。再记余数C=B%n。
由gcd(B,n)=gcd(B%n,n),且gcd(B,n)=1,可得余数C与n互质,即C为B的因子。此时B/C=A即为所求。

void solves(){
	int n,k;cin>>n;
	vector<int>ans;
	ll sum=1;
	for(int i=1;i<n;++i){
		if(__gcd(i,n)==1){
			ans.push_back(i);
			sum=(sum*i)%n;
		}
	}
	if(sum==1){
		cout<<ans.size()<<endl;
		for(auto& it:ans) cout<<it<<" ";cout<<endl;
	} else{
		cout<<(int)ans.size()-1<<endl;
		for(auto& it:ans){
			if(it!=sum) cout<<it<<" ";
		}cout<<endl;
	}
}
  • 14
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值