LibreOJ #6221. 幂数 !(数论+dfs+剪枝)

  写新题然后艹翻标程的感觉真是舒爽啊...

  这题就是个dfs。。。先预处理出sqrt(n)范围内的素数,然后dfs构造合法的数就行了。

  直接暴搜会TLE,需要剪一剪枝,不需要跑到最后一层再计算答案,边构造边更新答案,发现下一层无法出现新答案直接退出就行了

  效率大概O(答案个数)

  #6222也就是这题加强版需要高精度,出题人直接用python了= =   欺负C++高精度得手写...

  而且这种写法是过不了的QAQ,加强版就不是很会了

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int maxn=500010;
ull n,cnt,ans;
int p;
ull prime[maxn];
bool v[maxn];
void read(ull &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
void dfs(int dep,ull sum)
{
    if(dep==p)return;
    if(sum*prime[dep+1]*prime[dep+1]<=n)dfs(dep+1,sum);
    ull now=prime[dep];
    for(int i=2;;i++)
    {
        now*=prime[dep];
        if(sum*now>n)return;
        dfs(dep+1,sum*now);
        cnt++;ans+=sum*now;
    }
}
int main()
{
    read(n);int m=(int)sqrt(n);v[1]=1;
    for(int i=2;i*i<=m;i++)
    if(!v[i])for(int j=i<<1;j<=m;j+=i)v[j]=1;
    for(int i=2;i<=m;i++)if(!v[i])prime[p++]=i;
    cnt=ans=1;dfs(0,1);
    printf("%llu
%llu",cnt,ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Sakits/p/7441545.html