您的位置:首页 > 其它

【JZOJ4586】Ned 的难题

2016-07-08 18:59 369 查看

Description



Solution

其实这题是有一个有点暴力方法可以过的,而且速度还快,但是是针对题目贪心,速度当然比正解快。但是我们要为了学知识而做题,并不是为了做题而做题

对于每个数分解质因数,因为是乘法,所以每个质数在区间中的贡献是xmin(y),所以我们用数组fl[i][j]和fr[i][j]来计算每个数的第j个质因数的向左向右贡献区间(保证这段区间的min(y)就是当前这个a[i]的x分解出的次数)。

然后转移显然。

假如算xy,y很大怎么办。参见指数取模

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int mo=1000000009,maxn=100005;
int i,j,l,t,k,n,m,x,o,a[maxn];
int fl[maxn][10],fr[maxn][10],f[maxn][10],ci[maxn][10],da,p[maxn],b[maxn];
bool bz[maxn*100];
ll ans;
ll qsm(ll x,ll y){
ll z=1;
while(y){
if(y&1)z=z*x%mo;
x=x*x%mo;
y=y/2;
}
return z;
}
bool pan(int x,int y,int z){
if(!x)return 0;int o=0;
while(x%y==0)x/=y,o++;
if(o>=z)return 1;return 0;
}
int find(int x,int y){int i;fo(i,1,f[x][0])if(f[x][i]==y)return i;}
int main(){
freopen("ned.in","r",stdin);
freopen("ned.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)scanf("%d",&a[i]),da=max(da,a[i]);
fo(i,2,da){
if(!bz[i])p[++p[0]]=i;
fo(j,1,p[0]){
if(i*p[j]>da)break;bz[i*p[j]]=1;
if(!(i%p[j]))break;
}
}
fo(x,1,n){
t=a[x];
fo(i,1,p[0]){
if(p[i]>sqrt(a[x])+1)break;if(t<p[i])break;
if(!(t%p[i])){
f[x][++f[x][0]]=p[i];
while(!(t%p[i]))t/=p[i],++ci[x][f[x][0]];
}
}
if (t>1)f[x][++f[x][0]]=t,ci[x][f[x][0]]=1;
}
ans=1;
fo(i,1,n)fo(j,1,f[i][0]){
o=i-1;
while(pan(a[o],f[i][j],ci[i][j]))o=fl[o][find(o,f[i][j])];
fl[i][j]=o;
}
fod(i,n,1)fo(j,1,f[i][0]){
o=i+1;
while(pan(a[o],f[i][j],ci[i][j]+1))o=fr[o][find(o,f[i][j])];
fr[i][j]=o;
}
fo(i,1,n)fo(j,1,f[i][0])ans=ans*qsm(f[i][j],(ll)ci[i][j]*(i-fl[i][j])%(mo-1)*(fr[i][j]-i)%(mo-1))%mo;
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: