Description
Solution
先来搞一个反过来的暴力:
设当前处理到第i个,
bj(j<=i)
为
gcd(aj,aj+1...,ai)
,
现在再往后处理一个,那么
ans=ans∗ai+1∗∏j=1igcd(bj,ai+1)
,
b数组随之更新: bj=gcd(bj,ai+1) ,
复杂度: O(n2) ;
我们发现,对于每一个i, bi ~ b1 都是不上升的,而且每次减小至少都是/2,所有最多有 log2(n) 种,
还有,如果当前已经有一串数是相同的,无论i如何增加,这串数依旧是相同的,只是可能会整体减小,
这意味着会越来越多的数将会相同,也就是可以直接用快速幂跳过,
跳可以用并查集或者指针,
复杂度: O(nlog2(n))
Code
速度还不错~
#include<cstdio>
#include<cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long LL;
const int N=50500,mo=1e9+9;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n;
LL a[N],b[N],ans;
int c[N];
int gcd(int a,int b)
{
if(!b)return a;
return gcd(b,a%b);
}
LL ksm(LL q,LL w)
{
q%=mo;LL ans=1;
while(w)
{
if(w&1)ans=(ans*q)%mo;
q=(q*q)%mo;
w>>=1;
}
return ans;
}
int main()
{
freopen("ned.in","r",stdin);
freopen("ned.out","w",stdout);
int Q;LL q;
read(n);
fo(i,1,n)a[i]=b[i]=read(Q),c[i]=i;
ans=a[1];
fo(i,2,n)
{
ans=ans*a[i]%mo;
int j1=i;
for(int j=i-1;j;j=c[j]-1)
{
b[j]=gcd(b[j],b[j1]);
if(b[j]==b[j1])
{
c[j1]=c[j];
}
ans=ans*ksm(b[j],(j-c[j]+1))%mo;
j1=j;
}
}
printf("%lld\n",ans);
return 0;
}