P17784 山田凉不是罪过
题解:P17784 山田凉不是罪
思路
容易想到:让所有子任务贡献和最大,就要使除了分值最小的一个的子任务最容易全对,也就是分配 \(1\) 个测试点,而剩下的测试点全部分给分值最小的子任务。容易证明:当 \(a\) 从大到小排序时,\(\frac{a_1}{2} + \frac{a_2}{2} + \frac{a_3}{2} + ... + \frac{a_{n-1}}{2} + \frac{a_n}{2^{k-(n-1)}}\) 一定是最优选择。
具体证明的话,就是假设 k=4,n=2,\(\frac{a_1}{2}+\frac{a_2}{8}\) 一定大于 \(\frac{a_1}{4}+\frac{a_2}{4}\) 或 \(\frac{a_1}{8}+\frac{a_2}{2}\),篡改越大,答案越小。
剩下的就是费马小定理求逆元。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int p=998244353;
int qpow(int x,int y){
int ans=1;
while(y){
if(y&1)ans=ans*x%p;
x=x*x%p;
y/=2;
}
return ans;
}
int n,k;
int a[1000005];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
int mi=0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=k;i++){
cin>>a[i];
mi=min(mi,a[i]);
}
int ans=0;
bool f=0;
for(int i=k;i>=1;i--){
if(f||a[i]!=mi)ans=(ans+a[i]*qpow(2,p-2)%p)%p;
else f=1;
}
ans=(ans+mi*qpow(qpow(2,n-k+1),p-2)%p)%p;
cout<<ans<<"\n";
f=0;
for(int i=1;i<=k;i++){
if(f||a[i]!=mi)cout<<"1 ";
else{
cout<<n-k+1<<' ';
f=1;
}
}
return 0;
}

浙公网安备 33010602011771号