题目链接:https://vjudge.net/contest/356798#problem/H
题意:
在a,b中(a,b<=n)(1 ≤ n ≤ 1014),有多少组(a,b) (a<b)满足lcm(a,b)==n;
题解:
(注意原作者对于代码的构思,n过大时解决的常见套路)
先来看个知识点:
素因子分解:n = p1 ^ e1 * p2 ^ e2 *…*pn ^ en
for i in range(1,n):
ei 从0取到ei的所有组合
必能包含所有n的因子。
现在取n的两个因子a,b
a=p1 ^ a1 * p2 ^ a2 *…*pn ^ an
b=p1 ^ b1 * p2 ^ b2 *…*pn ^ bn
gcd(a,b)=p1 ^ min(a1,b1) * p2 ^ min(a2,b2) *…*pn ^ min(an,bn)
lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *…*pn ^ max(an,bn)
哈哈,又多了种求gcd,lcm的方法。
题解:
先对n素因子分解,n = p1 ^ e1 * p2 ^ e2 *…*pk ^ ek,
lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *…*pk ^ max(ak,bk)
所以,当lcm(a,b)==n时,max(a1,b1)==e1,max(a2,b2)==e2,…max(ak,bk)==ek
当ai == ei时,bi可取 [0, ei] 中的所有数 有 ei+1 种情况,bi==ei时同理。
那么就有2(ei+1)种取法,但是当ai = bi = ei 时有重复,所以取法数为2(ei+1)-1=2ei+1。
除了 (n, n) 所有的情况都出现了两次 那么满足a<=b的有 (2ei + 1)) / 2 + 1 个
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+7; //1e14中素数差不多1e6左右
const int NN=1e7+7;//常见套路,就是只遍历到sqrt,代码最后if语句判断一下就好
ll pri[N];
bool vis[NN];
void isprime() {
memset(vis,false,sizeof(vis));
for(int i=2; i<=NN; i++) {
if(!vis[i]) {
pri[++pri[0]]=i;
}
for(int j=1; j<=pri[0] && i*pri[j]<=NN; j++) {
vis[i*pri[j]]=1;
if(i % pri[j]==0) {
break;
}
}
}
}
// 欧拉筛
int main()
{
isprime();
ll n;
int t,cnt=0;
scanf("%d", &t);
while(t--) {
ll ans=1;
scanf("%lld", &n);
// for中的i<=pir[0]经常漏,要注意!
for(int i=1; i<=pri[0]&&pri[i]<=sqrt(n); i++) {
if(n%pri[i]==0) {
int e=0;
while(n%pri[i]==0) {
n/=pri[i];
e++;
}
ans*=(2*e+1);
}
}
//易漏:如果还有素因子,那么必定只有一个,且那个素因子为1次
if(n>1)
ans*=(2*1+1);
printf("Case %d: %lld\n",++cnt,(ans+1)/2);
}
return 0;
}