zoukankan      html  css  js  c++  java
  • Distinct powers (Project Euler 29 加强版)

    题目大意:

    $2<=a,b<=n$ 求 $a^b$能表示多少不同的正整数。 

    原题中n=100,可以直接暴力求解,常见的两种解法是写高精度或者取对数判断相等。 直觉告诉我应该有更加优秀的解法,于是翻了下discuss,找到了一种复杂度介于O(n)和O(nlognlogn)的解法,拿出来分享一下。

     

    首先来看一个性质:

    对于一个$a$,可以找到最小的$a_0$,使得$a=a_0^k$.

    比如$8^4=4^6=2^{12}$ 都是等价的。

     

    对于某个$a^b = (a_0^k)^{b}$, 它只可能和某些$a_0^{b_1}$,$(a_0^2)^{b_2}$,$(a_0^3)^{b_3} cdots (a_0^{k-1})^{b_{k-1}}$  等价。

    我们来看 $a_0^i (1<=i<k)$ 与 $a_0^k$ 所能表示的那些数会重复。

    显然$a_0^{lcm(i,k)}$ $a_0^{2*lcm(i,k)}$ $a_0^{3*lcm(i,k) cdots}$这些都是可以同时被$a_0^i (1<=i<k)$ 与 $a_0^k$ 表示的。

    对应到$a_0^k$的指数分别是 $frac{lcm(i,k)}{k}$  $2*frac{lcm(i,k)}{k}$  $3*frac{lcm(i,k)}{k} cdots$  把这些指数用一个bool数组标记,最后就可以得到以$a_0^k$为基能表示多少个数。 而且这个值和$a_0$的值无关,只和k有关,记为cnt[k],所以可以预处理。

    最后统计答案。 枚举$a_0(不能表示成另外一个数的幂的数)$把$a_0 a_0^2 a_0^3 cdots a_0^k$ 一起考虑,对答案的贡献就是cnt[1]+cnt[2]+...cnt[k].

    具体实现看代码:  实测n=100w 本地运行只要0.2s左右。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cmath>
     5 using namespace std;
     6 
     7 typedef long long ll;
     8 #define N 1000001
     9 #define M 21
    10 
    11 ll cnt[N];
    12 bool flag[N];
    13 bool vis[M][N];
    14 
    15 int gcd(int x,int y)
    16 {
    17     int tmp;
    18     while (y)
    19     {
    20         tmp=x%y;
    21         x=y; y=tmp;
    22     }
    23     return x;
    24 }
    25 
    26 int lcm(int x,int y){return 1ll*x*y/gcd(x,y);}
    27 
    28 int main()
    29 {
    30     //freopen("in.in","r",stdin);
    31     //freopen("out.out","w",stdout);
    32     
    33     int n,m=1; scanf("%d",&n);
    34     for (int i=2;i<=n;i<<=1,m++); m--;
    35     
    36     for (int i=2;i<=m;i++)
    37     {
    38         for (int j=1;j<i;j++)
    39         {
    40             int l=lcm(i,j),len1=l/j,len2=l/i;
    41             for (int k=1;k*len1<=n;k++) vis[i][k*len2]=true;
    42         }
    43     }
    44     cnt[1]=n-1;
    45     for (int i=2;i<=m;i++)
    46     {
    47         cnt[i]=cnt[i-1];
    48         for (int j=2;j<=n;j++) if (!vis[i][j]) cnt[i]++;
    49     }
    50     
    51     ll ans=0;
    52     for (int i=2;i<=n;i++)
    53     {
    54         if (flag[i]) continue;
    55         int p=0; ll x=i;
    56         do
    57         {
    58             flag[x]=true;
    59             p++; x*=i;
    60         }while (x<=n);
    61         ans+=cnt[p];
    62     }
    63     cout<<ans<<endl;
    64     return 0;
    65 }
  • 相关阅读:
    织梦dedecms上传漏洞uploadsafe.inc.php修复
    dedecms漏洞修复大全含任意文件上传漏洞与注入漏洞
    DEDECMS批量导入excel数据到后台文章系统的开发教程
    使用DEDE织梦计划任务功能定时更新首页
    如何解决织梦DedeCms文章标题字数长度限制的方法教程
    织梦后台点击网站主页跳转到../index.php?upcache=1删除方法
    dedecms漏洞修复大全含任意文件上传漏洞与注入漏洞
    dedecms模板中联动菜单高级使用技巧
    解决dede的loop中无法使用limit的方案+文章前数字序号
    DEDECMS 又一种隔行换色和分组加线的方法
  • 原文地址:https://www.cnblogs.com/vb4896/p/6354038.html
Copyright © 2011-2022 走看看