Codefroces 1362B Johnny and Grandmaster (贪心+hash)
题意
给你n和p,还有n个p的指数,问你怎么分可以让AB两个集合的和的差最小,n,p<=1e6,答案需要模1e9+7
思路
分成两组的问题参考51nod2334,朴素方法是背包或者dfs
但这题是在p进制下的,可以想到贪心的策略:
从大到小进行分配,每次将\(p^{a[i]}\)分配到当前的和比较小的集合当中
我们不妨令等于的时候都放到B集合里,对答案没有影响
由于是从大到小,根据p进制下的性质,在操作的过程中会恒有\(Sum_A\leq Sum_B\)
由于答案为ans=\(Sum_B-Sum_A\)
我们只需要根据ans是否为零来判断当前指数对答案是正贡献还是负贡献即可
因为判断的是ans的真值是否为零,而我们维护的是模意义下的值,所以需要通过双hash判断真值
代码
int n,m;
int a[maxn];
int fp(int a, int n, int mod){
int ans = 1;
while(n){
if(n&1)ans=1ll*ans*a%mod;
n>>=1;
a=1ll*a*a%mod;
}
return ans;
}
int p,mx;
int main() {
int t;
scanf("%d", &t);
while(t--){
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
sort(a+1,a+1+n);
int c = 19270817;
int ans1 = 0, ans2 = 0;
for(int i = n; i >= 1; i--){
if(!ans1&&!ans2){
ans1=(1ll*ans1+fp(m,a[i],mod))%mod;
ans2=(1ll*ans2+fp(m,a[i],c))%c;
}
else{
ans1=(1ll*ans1-fp(m,a[i],mod)+mod)%mod;
ans2=(1ll*ans2-fp(m,a[i],c)+c)%c;
}
}
printf("%d\n",ans1);
}
return 0;
}