东东对这个性质充满了好奇,东东现在给出一个整数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
#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;
} // 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;
}
/*
对于每一个数,分两种情况:
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;
}