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
2k−1,即每个元素在二进制中最大为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)
(2k−1)∗(n−1)。
如例子:
在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;
}
}