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_Aleq 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
",ans1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/13048895.html