暑假D16 T2 无聊 (深搜)

题意

求[1,n]区间内拥有最多约数的约数的数,输出他和她约数的约数个数,如12的约数1,2,3,4,6,12,这些数有1,2,2,3,4,6个约数,那么12就有18个约数的约数。

对于100%的数据,n<=1e18

题解

暴力还是比较好想

const int maxn=2000005;
ll n;
ll num[maxn],sum[maxn];//约数个数,约数的约数和 
ll ans;

int main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        num[i]++;
        sum[i]+=num[i];
        if(sum[i]>sum[ans]) ans=i;
        for(ll j=2*i;j<=n;j+=i){
            num[j]++;
            sum[j]+=num[i];
        }
    }
    //for(int i=1;i<=n;i++) printf("%d ",sum[i]);
    printf("%d\n%d",ans,sum[ans]);
}
View Code

本来想打表发现一些东西,一个答案会管辖区间,1e7内区间才70个不到,而且区间长度就是一些有最多约数的约数的数,本来想从这下手,但是长度也不是单增,就GG了。

正解就是一些数论的东西了。

对于一个数n,可以分解成p1r1p2r2...pmrm,他的约数个数就是(r1+1)(r2+1)....(rm+1)个;

通过上面可以发现,约数个数只与指数有关,所以在约数个数相同时,ri>=ri+1会更优;

根据乘法分配律n的约数和为(1+p1+p12+...p1r1)(1+p2+p22+...p2r2)...(1+pm+pm2+...pmrm),那么类比过来约数的约数个数就是(1+2+..+(r1+1))(1+2+...+(r2+1))...(1+2+...+(rm+1)),可以想象成在每个括号中选一个数,那么就会是一个约数的指数搭配方式,这与最左的数的对应取法得到的约数是一样的。

可以发现这个也只与指数有关,所以ri>=ri+1也会更优

而且1e18的数分成不一样的质数最多到53,那么就可以爆搜了

#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll n;
int prime[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
ll ans1,ans2;

void dfs(int pos,ll ret,ll num,int last){
    if(ret>n) return;
    if(num>ans2){
        ans2=num;
        ans1=ret;
    }
    else if(num==ans2)
     ans1=min(ans1,ret);
    for(int i=1;i<=last&&ret<=n/prime[pos];i++){
        ret*=prime[pos];
        dfs(pos+1,ret,num*((i+1)*(i+2))/2,i);
    }
}

int main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%lld",&n);
    dfs(1,1,1,60);
    printf("%lld\n%lld",ans1,ans2);
}
View Code

猜你喜欢

转载自www.cnblogs.com/sto324/p/11266192.html
D16