牛客算法周周练5

链接:https://ac.nowcoder.com/acm/contest/5556/B
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

东东对幂运算很感兴趣,在学习的过程中东东发现了一些有趣的性质: 9^3 = 27^2, 2^10 = 32^2
东东对这个性质充满了好奇,东东现在给出一个整数n,希望你能帮助他求出满足 a^b = c^d(1 ≤ a,b,c,d ≤ n)的式子有多少个。
例如当n = 2:
1^1=1^1
1^1=1^2
1^2=1^1
1^2=1^2
2^1=2^1
2^2=2^2
一共有6个满足要求的式子

输入描述:

输入包括一个整数n(1 ≤ n ≤ 10^6)

输出描述:

输出一个整数,表示满足要求的式子个数。因为答案可能很大,输出对1000000007求模的结果

示例1

输入

2

输出

6

题解from:https://www.jianshu.com/p/41fbd79255bd

从易到难分三种情况分析:

  1. 以1为底的式子
  2. 1以外的数为底的式子
  3. 幂关系

问题

  1. (x / y) = (d / c)怎么来的?
    9^{3} = 27^{2},2^{10} = 32^2分析
    9^{3} = 27^{2}Rightarrow {3^2}^{3} = {3^3}^{2} Rightarrow 3^{2 	imes 3} = 3^{3 	imes 2} = 3^6
    2^{10} = 32^2 Rightarrow {2^1}^{10} = {2^5}^2 Rightarrow 2 ^{1 	imes 10} = 2 ^{5 	imes 2} = 2^{10}
    i表示底数,用x,y,b,c表示指数,那么存在关系(i ^ x) ^ c = (i ^ y) ^d。根据幂的指数乘方运算法则x * c = y * d, 问题转换为找到满足(x / y) = (d / c)的个数。
  2. 为什么要使用(x/y)=(d/y)?
    因为比较容易计算,d/cx/y经过约分后,最简分数一样。如果x/y是最简分数,那么d/cx/y的倍数。
  3. x,y如何确定?
    x,yi的幂值,可以通过枚举i获得。i^x≤ni^y≤n,因此可以遍历i的各个幂值。
  4. 为什么要y/gcd(x,y)?
    因为x/y要约分,使x/y成为最简分数。y/gcd(x,y)是约分后的分母,同样x/gcd(x,y)是约分后的分子。
  5. 为什么n要除以y/gcd(x,y)?
    x/y经过约分后,成为最简分数。y/gcd(x,y)是最简分数的分母,n/(y/gcd(x,y))表示n内有多少个最简分母的倍数,也就是有多少组cd
  6. 为什么*2?因为等号左右交换位置也算一种情况,所以*2


 1 #include <bits/stdc++.h>
 2 typedef long long LL;
 3 #define pb push_back
 4 const int INF = 0x3f3f3f3f;
 5 const double eps = 1e-8;
 6 const int mod = 1e9+7;
 7 const int maxn = 1e5+10;
 8 using namespace std;
 9 
10 set<int> st;
11 
12 int gcd(int a, int b)
13 {
14     return b?gcd(b,a%b):a;
15 }
16 
17 int main()
18 {
19     #ifdef DEBUG
20     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
21     #endif
22     
23     int n;
24     scanf("%d",&n);
25     LL ans = (1LL*n*(2*n-1))%mod;
26     for(int i=2;i*i<=n;i++)
27     {
28         if(st.find(i)!=st.end()) continue; //如果已经存在则跳过
29         LL t=i;
30         int num=0;
31         while(t<=n) //求关于i的<=n的最大幂
32         {
33             st.insert(t);
34             t*=i;
35             num++;
36         }
37         for(int x=1;x<=num;x++) //遍历统计到的幂
38         {
39             for(int y=x+1;y<=num;y++)
40             {
41                 ans=(ans+n/(y/gcd(x,y))*2LL)%mod;
42             }
43         }
44     }
45     printf("%lld
",ans);
46     
47     return 0;
48 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12853276.html