题意:给出n个数,和一个质数x,令sum=Σai,求s=Σ(x^(sum-ai))和t=x^sum的最大公约数。
思路:在网上看题解推了一大篇公式……顿时感到无力,最后只能用模拟提取公因式的方式过了。由于x是一个质数,因此这两个数的最大公约数一定是x^k的形式,只要求出k,那么就可以用快速幂求解了。如何求k呢?分母直接就给出了,对于分子来说,先把他们排序,然后提取最小的因子,此时会有一些数字提取以后指数为0了,把这些数的结构计算出来后,如果不能再提取,那么结果就是当前已经提取的数,否则继续提取。最后和分母的幂次求较小值就行了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
const int mod=1000000000+7;
ll num[maxn],a[maxn];
ll f(ll x,ll y)
{
ll res=1,b=x;
while(y)
{
if(y&1) res=(res*b)%mod;
b=(b*b)%mod;
y>>=1;
}
return res;
}
ll cal(ll x,ll y)
{
ll ret=0;
while(x&&(x%y==0))
{
ret++;
x/=y;
}
return ret;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,x;
while(~scanf("%d%d",&n,&x))
{
ll sum=0;
for(int i=0;i<n;++i)
{
scanf("%I64d",&a[i]);
sum+=a[i];
}
for(int i=0;i<n;++i)
num[i]=sum-a[i];
sort(num,num+n);
ll cnt=0,ont=1,op=num[0],tmp;
int p=0;
while(true)
{
while(p+1<n&&num[p+1]-cnt==op) ont++,p++;
cnt+=op;
if((ont%x)||(op==0))
{
tmp=min(cnt,sum);
ll ans=f(x,tmp);
printf("%I64d\n",ans);
break;
}
op=cal(ont,x);
if(p+1<n) op=min(op,num[p+1]-cnt);
for(int i=0;i<op;++i) ont/=x;
}
}
return 0;
}