题目链接:https://codeforces.com/contest/1362/problem/E
题目大意:
多样例:一个n和p,下面输入n个数k[i],每个数代表p^k[i],把这些数分成两组。使他们的和的差值最小。输出这个差值mod 1e9+7。
思路一:把k[i]从大到小排序,如果k[i]为偶数,这个各种分配一半。如果为奇,那么一个就分配多了一个。我们希望用后面的 k[i]去弥补这个差值。模拟这个过程就可以了。
思路二:直接用哈希暴力搞过去。
#include <bits/stdc++.h> #define LL long long using namespace std; const LL mod=1000000007; LL k[1000005]; LL quick_pow(LL a, LL b){ if(a==0){ return 0; } LL ans=1; while(b){ if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } int main(){ int t; scanf("%d", &t); while(t--){ LL n, p; scanf("%lld%lld", &n, &p); for(int i=1; i<=n; i++){ scanf("%lld", &k[i]); } sort(k+1, k+1+n, greater<int>() ); if(n%2==0&&p==1){ printf("0\n"); continue; } else if(p==1){ printf("1\n"); continue; } LL pos=0, A=0, pos2=0; for(int i=1; i<=n; ){ LL x=k[i], r=i+1, y=1; while(k[r]==x&&r<=n){ r++; y++; } LL L=pos; int fg=0; for(int k=1; k<=A-x&&pos&&p!=1; k++){ L*=p; if(L>n-i+1){ fg=1; } } if(fg==0) pos=L; if(fg){ for(LL pos=i; pos<=n; pos++){ LL x=k[pos]; pos2+=(quick_pow(p, x))%mod; pos2%=mod; } break; } LL c=y; if(pos>=c){ pos-=c; A=x; } else{ c-=pos; if(c%2) pos=1, A=x; else pos=0; } i+=y; } printf("%lld\n", ((pos*quick_pow(p, A))%mod-pos2+mod)%mod); } return 0; } #include <bits/stdc++.h> #define LL long long using namespace std; const LL mod1=1000000007; const LL mod2=10995514; const LL mod3=200000011; LL k[1000005]; LL quick_pow(LL a, LL b, LL mod){ if(a==0){ return 0; } LL ans=1; while(b){ if(b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } int main(){ int t; scanf("%d", &t); while(t--){ LL n, p; scanf("%lld%lld", &n, &p); for(int i=1; i<=n; i++){ scanf("%lld", &k[i]); } sort(k+1, k+1+n, greater<int>() ); LL ans1=0, ans2=0, ans3=0, sig=0; for(int i=1; i<=n; i++){ sig=-1; if(ans1==0&&ans2==0&&ans3==0){ sig=1; } ans1=(ans1+quick_pow(p, k[i], mod1)*sig+mod1)%mod1; ans2=(ans2+quick_pow(p, k[i], mod2)*sig+mod2)%mod2; ans3=(ans3+quick_pow(p, k[i], mod3)*sig+mod3)%mod3; } cout<<ans1<<endl; } return 0; }