题意:
给定n个数和p,现在你需要将n个数分成两个集合A,B 使得两个集合差值绝对值最小
解析:
一贯的套路
我们把pk[i] 当成p进制下,第k[i]位为1.
那么就出现了一个性质 25 > 20 + 21 + 22 + 23 +24
所以我们按照k[i] 从大到小排
第一步找到最大的k[i] ,ans+=pk[i] 相当于把k[i] 放到A集合中
第二步 ans-=pk[i] 相当于把k[i]放到B集合中, 直到ans=0 再回到第一步去即可
最后还有一个问题,就是ans=0 。如果ans是MOD的倍数的话,就会出错。
所以需要双模 再用一个res变量记录 。 当res ==0 && ans == 0 才能回到第一步
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e6+1000;
const int MOD=1e9+7,mod=1e9+3;
ll a[N];
int t,n;
ll p;
ll quick(ll a,ll b,ll x)
{
ll res=1%x;
while(b)
{
if(b&1) res=res*a%x;
a=a*a%x;
b>>=1;
}
return res;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d %lld",&n,&p);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
if(p==1){
if(n&1) puts("1");
else puts("0");
continue;
}
sort(a+1,a+1+n,greater<int>());
ll ans=0,res=0;
for(int i=1;i<=n;i++)
{
if(!ans&&!res) ans=(ans+quick(p,a[i],MOD)),res=res+quick(p,a[i],mod);
else{
ans=((ans-quick(p,a[i],MOD))%MOD+MOD)%MOD;
res=((res-quick(p,a[i],mod))%mod+mod)%mod;
}
}
printf("%lld\n",ans);
}
}