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;
}


posted @ 2026-11-07 16:59  halewu  阅读(2)  评论(0)    收藏  举报