A. Ezzat and Two Subsequences
题意:把一个序列分成两个非空的子序列使两个序列的平均值最大。
题解:把最大的值单独提出来作为一个子序列,其他的分为一个子序列,此时两个子序列的平均值最大。
代码:
#include<bits/stdc++.h>
using namespace std;
long long a[100010];
int main(){
int T;cin>>T;
while(T--){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
double ans=0;
for(int i=1;i<=n-1;i++) ans+=a[i];
ans/=n-1;
ans+=a[n];
printf("%.9lf\n",ans);
}
}
这里我采用的是先排序再做运算,其实可以在读入过程中找出序列中的最大值和并用一个变量去存序列的和,然后再做运算,这样时间复杂度会更低一点。
B. Moamen and k-subarrays
题意:将数组划分成若干个子数组,通过对这些子数组排序使整个数组变成非递减数组,判断是否能将数组分成k个子数组使得将这些子数组排序后整个数组按非递减排序。
题解:我们可以求出需要的子数组数量的最小值cot,判断cot是否小于k。
因为要把划分好的子数组排序成非递减数组,所以我们可以把数组中连续的数组成一个子数组,再排序。这样就可以使子数组数量最少化了。
这个时候我们只需要记录数组中每个数的下标,并对数组排序,计算出下标非连续的数组的数量+1,即最少需要的子数组数量。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
int pos,v;//用pos记录位置,v记录值
}p[100010];
int cmp(node a,node b){
return a.v<b.v;//按值从小到大排序
}
signed main(){
int T;cin>>T;
while(T--){
int n,k,cot=0;cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>p[i].v;p[i].pos=i;
}
sort(p+1,p+1+n,cmp);
for(int i=2;i<=n;i++){
if(p[i].pos!=p[i-1].pos+1) cot++;//如果两个连续的值之间下标不连续,子数组数量+1
}
if(k>cot) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
C. Moamen and XOR
题意:构造一个长度位n的数组,每个元素的值小于,计算有多少种构造方式使得a1&a2...&an>=a1^a2...^an。
题解:&(与运算)和^(异或运算)都是针对二进制数的运算。
n个数经过^(异或)操作后:
1.若第i位上1的数目为奇:第i位上为1
2.若第i位上1的数目为偶:第i位上为0
n个数经过&(与)操作后:
1.若第i位上没有0存在:第i位上为1
2.若第i位上有0存在:第i位上为0
所以需要分情况判断n的奇偶性。
当n为奇数时:
当a1&a2...&an>a1^a2...^an。(&>^):对于任意一位上需要使与运算的结果大于异或运算。当该位上有0出现时,&(与运算)的结果为0 <= ^(异或运算)的结果,不成立。当该为上全为1时,&(与运算)结果为1,因为n为奇数,经过奇数次^(异或运算)后结果为1,& == ^。所以当n为奇数时,与运算大于异或运算的构造是无法实现的。
当a1&a2...&an=a1^a2...^an。 (&=^): 对于任意一位上需要使与运算的结果等于异或运算。当该位上有偶数个0出现时,&运算的结果等于^运算的结果(0的数量为0时,&运算和^运算的结果都为1;0的数量为n时,&运算和……运算的结果都为0)。
此时构造的方案数为
所以当n为奇数时方案数为:
当n为偶数时:
当a1&a2...&an=a1^a2...^an。 (&=^): 对于任意一位上需要使与运算的结果等于异或运算。当该位上有偶数个0出现时,&运算的结果等于^运算的结果(与n位奇数不同的是,0的个数不能为n,当0的个数为n时,&运算结果为1,^运算结果为0,&>^)
所以方案数为
当a1&a2...&an>a1^a2...^an。(&>^):枚举i个位置上的方案数(0 <= i < k)。当i位上全为1时,保证n个数的i+1位到k位相等(运用&=^时的构造方案),0到i-1位之间随意组合即可。所以方案数为
所以当n为偶数时方案数为。
代码:
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define ll long long
#define int long long
#define endl '\n'
const int maxn=2e5+5;
int qpow(int base,int index){//快速幂
int ret=1;
while(index){
if(index&1) ret=ret*base%mod;
base=base*base%mod;
index>>=1;
}
return ret;
}
signed main(){
int T;cin>>T;
while(T--){
int n,k,ans;cin>>n>>k;
if(n&1){
ans=qpow(qpow(2,n-1)+1,k)%mod;
}else{
ans=qpow(qpow(2,n-1)-1,k)%mod;
for(int i=0;i<k;i++){
ans=(ans+((qpow((qpow(2,n)),i)%mod)*qpow(qpow(2,n-1)-1,k-i-1)%mod)%mod)%mod;
}
}
cout<<ans<<endl;
}
}