Codeforces Round #713 (Div. 3)-G - Short Task(质因子分解)

题目大意:

让我们用d(n)表示数字n的所有约数之和,即d(n)=∑k|nk。

例如,d (1) = 1, d (4) = 1 + 2 + 4 = 7, d(6) = 1 + 2 + 3 + 6 = 12。

对于一个给定数字c,找出使d(n)=c的最小n。

思路:

我们考虑nlogn的预处理,然后每次询问O(1)

也就是需要一个logn的分解质因子的方法

我们在用欧拉筛素数的时候,顺便处理出每个数的最小质因子

然后我们质因子分解的时候,我们每个数除她的最小质因子求幂

这样最坏情况下logn的(逃)

然后分解完质因子考虑如何求所有因子的和

 

用这个公式就好了,等比数列求和然后相乘

 

 

ll qpow(ll a, ll b) {
    ll ans = 1;
    while(b) {
        //    if(b & 1) ans = ans * a % mod;
        if(b & 1) ans = ans * a ;
        //    a = a * a % mod;
        a = a * a ;
        b >>= 1;
    }
    return ans;
}
int  x,p[10000002],vis[10000002],mi[10000002];
void oula() {
    for(int i=2 ; i<=10000001; i++) {
        if(vis[i]==0) p[++x] = i,mi[i]=i;
        for(int j=1 ; j<=x&&p[j]*i<10000002; j++) {
            vis[i*p[j]]=1;
            mi[i*p[j]] = p[j];
            if(i%p[j]==0) break;
        }
    }
}
 
ll cal(ll x) {
    ll temp=1;
 
    while(x>1) {
        ll  t = mi[x];
        ll sum=0;
        while(x%t==0) x/=t,sum++;
        temp*=(qpow(t,sum+1)-1)/(t-1);
        if(temp>10000000) return 10000001;
    }
    return temp;
}
int  c,a[10000002];
int main() {
    oula();
    for(int i=1 ; i<=10000000 ; i++) {
        ll num = cal(i);
        if(num<=10000000) {
            if(a[num]==0) a[num] = i;
            else continue;
        }
    }
    int _ ;
    _ = read();
    while(_--) {
        c=read();
        if(a[c]) out(a[c]);
        else out(-1);
        puts("");
    }
    return  0 ;
}
View Code

 

1933ms(逃)

听说隔壁数论爷用狄利克雷前缀和400+就过了

posted @ 2021-04-11 17:03  UpMing  阅读(138)  评论(0编辑  收藏  举报