Problem F
LCM Cardinality
Input: Standard Input
Output: Standard Output
Time Limit: 2 Seconds
A pair of numbers has a unique LCM but a single number can be the LCM of more than one possible pairs. For example 12 is the LCMof (1, 12), (2, 12), (3,4) etc. For a given positive integer N, the number of different integer pairs with LCM is equal to N can be called theLCM cardinality of that number N. In this problem your job is to find out the LCM cardinality of a number.
Input
The input file contains at most 101 lines of inputs. Each line contains an integer N (0<N<=2*109). Input is terminated by a line containing a single zero. This line should not be processed.
Output
For each line of input except the last one produce one line of output. This line contains two integers N and C. Here N is the input number and C is its cardinality. These two numbers are separated by a single space.
Sample Input Output for Sample Input
2 12 24 101101291 0 | 2 2 12 8 24 11 101101291 5 |
Problem setter: Shahriar Manzoor
Special Thanks: Derek Kisman
题意:
输入正整数n,统计有多少对正整数a<=b,满足lcm(a, b) = n。
最开始想的方法想到最后一点的时候没有想出来。
对n进行质因式分解:
n = p1^r1 * p2^r2 * ... * px^rx
设:
a = p1^a1 * p2^a2 * ... * px^ax
b = p1^b1 * p2^b2 * ... * px^bx
根据lcm的定义可以知道 ri = max(ai, bi)
假设不考虑a<=b这个条件 则
对于pi,肯定有一个取ri,另外一个随便取有ri+1,所以有(ri+1)*2-1(因为有一种a==b算了两次)=ri*2+1种方案
而ab没有限制所以各个pi之间方案数独立,所以各个pi之间相乘即可
现在考虑a<=b
因为(a1, b1)和(b1, a1)重复了 而恰好包含了a==b的情况(即所有因子ab都取最大)
则 ans = (ans + 1) / 2
另外一种暴力求法
把n的所有因子就出来,然后枚举两个因子 看他们的lcm是否等于n,如果是方案数+1
先挖个坑,另外两个题
坑填上了
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
int vis[maxn], prim[maxn];
int A[maxn];
void sieve(int n) {
int m = (int) sqrt(n+0.5);
memset(vis, 0, sizeof(vis));
for(int i=2; i<=m; i++) if(!vis[i]) {
for(int j=i*i; j<=n; j+=i) {
vis[j] = 1;
}
}
}
int getPrimeTable(int n) {
sieve(n);
int c = 0;
for(int i=2; i<=n; i++) if(!vis[i])
prim[c++] = i;
return c;
}
int main() {
int n;
int primNum = getPrimeTable(100000);
while(scanf("%d", &n) != EOF && n) {
int nn = n;
memset(A, 0, sizeof(A));
for(int i=0; i<primNum && n>1; i++) {
while(n % prim[i] == 0) {
A[i]++;
n /= prim[i];
}
}
LL ans = 1;
for(int i=0; i<primNum; i++) if(A[i]) {
ans *= (2 * A[i] + 1);
}
ans = (ans + 1) / 2;
printf("%d %lld\n", nn, ans);
}
return 0;
}
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
int A[maxn];
int gcd(int a, int b) {
return b ? gcd(b, a%b) : a;
}
int lcm(int a, int b) {
return (LL) a * b / gcd(a, b);
}
int main() {
int n;
while(scanf("%d", &n) != EOF && n) {
memset(A, 0, sizeof(A));
int num = 0;
int m = (int) sqrt(n+0.5);
for(int i=1; i<=m; i++) if(n % i == 0) {
A[num++] = i;
A[num++] = n / i;
}
if(A[num-1] == A[num-2]) num--;
int ans = 0;
for(int i=0; i<num; i++) {
for(int j=i; j<num; j++) if(lcm(A[i], A[j]) == n) {
ans ++;
}
}
printf("%d %d\n", n, ans);
}
return 0;
}