【NOIP模拟】腐败

Description

【NOIP模拟】腐败_第1张图片

Solution

刚看到这种题,就想开始繁衍。。。。。。不对啊,这种东西怎么繁衍,并显示暴力加优化!
对每个数分解质因数,然后对每个因数开一个桶做,是不是很水。

怎么处理空间问题

可以动态开桶,但有一种更机智的方法。
因为如果有一个质数大于 107 ,那么这些质数在一个数分解质因数是最多只会出现一次,那么我们就有很多的质数不用刻意再取开一个桶了,直接用一个数组统计起来就可以了。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=30007,da=10000000;
const ll mo=100000000009;
ll i,j,k,l,n,m,ans,tt;
int a[maxn],p[da],shu[da+1];
int t[4000][20],duo[4400];
bool bz[da];
ll gcd(ll x,ll y){
    ll o=1;
    while(o){
        o=x%y;
        x=y;
        y=o;
    }
    return x;
}
ll qs(ll x,ll y){
    ll z=0;
    if(y==0)return z;
    z=qs(x,y/2);
    z=z*2%mo;
    if(y%2==1)z=(z+x)%mo;
    return z;
}
ll qsm(ll x,ll y){
    ll z=1;
    while(y){
        if(y&1==1)z=qs(z,x)%mo;
        x=qs(x,x)%mo;
        y/=2;
    }
    return z;
}
ll suan(ll x,ll y){
    ll z=(x-y+1);
    return (z+x)*y/2;
}
int main(){
//  freopen("fan.in","r",stdin);
    fo(i,2,sqrt(da)){
        if(!bz[i])p[++p[0]]=i;
        fo(j,1,p[0]){
            tt=p[j]*i;if(tt>sqrt(da))break;bz[tt]=1;
        }
    }
    scanf("%lld",&n);
    ans=1;
    fo(i,1,n){
        scanf("%lld",&a[i]);
        ans=qs(ans,a[i]);
        if(ans==0){
            ans=ans;
        }
        ll u=a[i];
        fo(j,1,p[0]){
            if(u==1)break;
            if(u%p[j]==0){
                ll y=0;
                duo[j]++;
                while(!(u%p[j]))u=u/p[j],y++;  
                t[j][y]++;  
            }
        }
        if(u>1){
            if(shu[u])ans=qs(ans,qsm(u,shu[u]));
            shu[u]++;
        }
    }
    fo(i,1,p[0]){
        ll o=1,d=0;
        if(duo[i]==0)continue;
        fo(j,1,20){
            if(d==duo[i])break;
            o=qs(o,p[i]%mo);
            ans=qs(ans,qsm(o,suan(duo[i]-d-1,t[i][j]))); 
            d+=t[i][j];
        }
    }
    printf("%lld",ans);
}

你可能感兴趣的:(noip,数论,暴搜)