东东对这个性质充满了好奇,东东现在给出一个整数n,希望你能帮助他求出满足 a^b = c^d(1 ≤ a,b,c,d ≤ n)的式子有多少个。
例如 n = 2:
1^1=1^1
1^1=1^21^2=1^1
1^2=1^2
2^1=2^1
2^2=2^2
一共有 6 个满足要求的式子
数据范围:
,答案对
取模
输入包括一个整数n(1 ≤ n ≤ 10^6)
输出一个整数,表示满足要求的式子个数。因为答案可能很大,输出对1000000007求模的结果
2
6
// diL 等式左值底数, diL 等式右值底数
// ciL 等式左值次数, ciR 等式右值次数
// 1-n的数每一个数i都对应着一堆以之为底的1-n的数,有di = i^ci
// 对于每一个数,分两种情况:
// 1.diL==diR,这种情况共有n*n (对应1)+n*(n-1) (对应2-n)种情况
// 2.diL != diR, 遍历左右值即可,对于一对diL,diR有n / (ciR / (ciR和ciL的公约数)) * 2种情况
// 这里n / (ciR / (ciR和ciL的公约数))求的是i在1-n范围时,i ciL/ciR为正整数的个数,
// 这里对于ciR的所有因子,一部分由ciL(也就是二者的最大公约数)提供,一部分由i提供。
// long long 大法好!
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
unsigned int gcd(unsigned int i, unsigned j) {
unsigned int res = j % i;
while(res) {
j = i;
i = res;
res = j % i;
}
return i;
}
int main() {
unsigned long long n;
cin >> n;
set<unsigned long long> sDis;
unsigned int index = 2;
unsigned long long count = (n * (n - 1) + n * n) % mod;
while(index * index <= n) {
unsigned long long diL = index;
if(sDis.find(diL) != sDis.end()) {
index++;
continue;
}
unsigned long long tmp = index;
while(tmp <= n) {
sDis.insert(tmp);
tmp *= index;
}
unsigned int ciL = 1;
while(diL <= n) {
unsigned ciR = ciL + 1;
unsigned diR = diL * index;
while(diR <= n) {
count = (count + (n / (ciR / gcd(ciL,ciR)) * 2)) % mod;
ciR++;
diR = diR * index;
}
ciL++;
diL = diL * index;
}
index++;
}
cout << count <<endl;
}
#include <bits/stdc++.h> using namespace std; const int M = 1e9+7; typedef long long ll; int main(){ int n; scanf("%d", &n); ll s = (ll)n*(n*2-1)%M; set<int> S; for(int i=2;i*i<=n;i++){ if(S.find(i)!=S.end()) continue; int cnt=0, k=i; while(k<=n){ S.insert(k); k *= i; cnt++; } for(k=1;k<=cnt;k++) for(int j=k+1;j<=cnt;j++) s = (s + n/(j/__gcd(k,j))*2) % M; } printf("%lld\n", s); return 0; }
/* 对于每一个数,分两种情况: 1.a==c,这种情况共有n*n (对应1)+n*(n-1) (对应2-n)种情况,就是a,c底数为1时,有n*n种情况;a==c且不等于1时有n-1种(2~n),bd相等的情况有n种(1~n)。 2.a != c, 遍历左右值即可,对于一对a,c有n / (x和y中的较大值/ (x和y的公约数)) * 2种情况 a^b=c^d----->(i^x)^b = (i^y)^d 遍历i,且i^x<=n、j^y<=n,求出x和y的范围,除去底数相同的情况,i*i必定小于n 遍历x和y,取出x和y的最大公约数放到底数做i的指数,(i^m)^n1*b = (i^m)^n2*d 转换成求n1*b==n2*d 有多少种情况, x和y的最大值除以最大公约数m假设为n1,b/d=n2/n1,求有多少的b/d使得等式成立,n1>n2,b、d<n 所以构造d为n1的倍数即可,总的倍数有n/n1个。同时等式两边可以对调,因此*2 */ #include<iostream> #include<set> using namespace std; int MOD = 1000000000 + 7; int gcd(int a,int b){ return (a % b == 0) ? b : gcd(b,a%b); } int main() { int n; cin>>n; //int会越界,且还需要强制类型转换 long long ans =(long long) 1*n*(n*2-1) % MOD; set<int> s; //遍历i,因为去除了底数相同的情况,所以底数不等的情况下:底数必定大于1,次方必定大于1——>底数小于n的开方 for (int i = 2; i*i <= n; i++){ if (s.find(i)!=s.end()) continue; int tmp = i; int cnt = 0; //满足条件的底数,同时求x和y的范围 while(tmp <= n) { s.insert(tmp); tmp = tmp * i; cnt++; } //相同的公约数,放到下面,反正不会大于n for (int k = 1; k <= cnt; k++) { for (int j = k + 1; j <= cnt; j++) { ans = (ans + n / (j / gcd(k, j) ) * (long)2 ) % MOD; } } } cout<<ans<<endl; return 0; }
//尚未优化,主要用到快速幂 #include <iostream> long long pow(int a, int b){ long long curr = a,ans = 1, last; while (b){ if(b%2) ans *= curr; curr *= curr; b /= 2; } return ans; } int main(){ int a = 1; long long n = 282; long long all = 0; while (a <= n){ int b =1 ; while (b <= n){ int c =1 ; while (c <= n){ int d =1; while (d <= n){ if (pow(a, b) == pow(c, d)){ all++; } d++; } c++; } b++; } a++; } std::cout << all << std::endl; return 0; }