Light oj 1236 - Pairs Forming LCM (约数的状压思想)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1236

题意很好懂,就是让你求lcm(i , j)的i与j的对数。

可以先预处理1e7以内的素数,然后用来筛选出能被n整除的所有的素数以及素数的个数,时间复杂度是小于根号的。然后用DFS或者BFS选出所有的约数(不会很大)。

现在要是直接2个for利用gcd筛选lcm(x,y)==n的个数的话肯定超时,所以这里把每个素数看作一个位,比如:2 3 5这3个素因子,那我2可以看作2进制上的第一位(1),3第二位(10)...那一个约数就可以表示素因子相乘 也可以表示成一个二进制数 比如6表示成(11),那么要是两个约数的二进制数的'|'值等于n,那么lcm就等于n。然后处理出每个约数对应的二进制数。注意一点的是约数里的某个素因子不满其最大个数的话 就表示为0。

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <algorithm>
  6 #include <queue>
  7 using namespace std;
  8 typedef long long LL;
  9 typedef pair <LL , int> P;
 10 const int MAXN = 1e7 + 1000;
 11 vector <P> G;
 12 vector <LL> res;
 13 bool prime[MAXN];
 14 int p[MAXN / 9];
 15 
 16 void init() {
 17     prime[1] = true;
 18     int cont = 0;
 19     for(int i = 2 ; i < MAXN ; i++) {
 20         if(!prime[i]) {
 21             p[++cont] = i;
 22             for(int j = i * 2 ; j < MAXN ; j += i) {
 23                 prime[j] = true;
 24             }
 25         }
 26     }
 27 }
 28 /*
 29 DFS
 30 void dfs(int dep , int end , LL num) {
 31     if(dep == end) {
 32         res.push_back(num);
 33         return ;
 34     }
 35     LL temp = (1 << (dep));
 36     for(int i = 0 ; i < G[dep].second ; i++) {
 37         dfs(dep + 1 , end , num);
 38     }
 39     dfs(dep + 1 , end , num + temp);
 40 }
 41 */
 42 void bfs(int end) {
 43     queue <P> que;
 44     while(!que.empty()) {
 45         que.pop();
 46     }
 47     que.push(P(0 , 0));
 48     while(!que.empty()) {
 49         P temp = que.front();
 50         que.pop();
 51         if(temp.second == end) {
 52             res.push_back(temp.first);
 53         }
 54         else {
 55             for(int i = 0 ; i <= G[temp.second].second ; i++) {
 56                 if(i == G[temp.second].second) {
 57                     que.push(P(temp.first + (1 << temp.second) , temp.second + 1));
 58                 }
 59                 else {
 60                     que.push(P(temp.first , temp.second + 1));
 61                 }
 62             }
 63         }
 64     }
 65 }
 66 
 67 int main()
 68 {
 69     init();
 70     int t;
 71     LL n;
 72     scanf("%d" , &t);
 73     for(int ca = 1 ; ca <= t ; ca++) {
 74         scanf("%lld" , &n);
 75         printf("Case %d: " , ca);
 76         if(n == 1) {
 77             printf("1\n");
 78             continue;
 79         }
 80         res.clear();
 81         G.clear();
 82         for(int i = 1 ; (LL)p[i]*(LL)p[i] <= n ; i++) {
 83             if(n % p[i] == 0) {
 84                 int cont = 0;    
 85                 while(n % p[i] == 0) {
 86                     n /= p[i];
 87                     cont++;
 88                 }
 89                 G.push_back(P((LL)p[i] , cont));
 90             }
 91         }
 92         if(n > 1)
 93             G.push_back(P(n , 1));
 94         int ans = (1 << G.size()) - 1 , cont = 0;
 95         //dfs(0 , G.size() , 0);
 96         bfs(G.size());
 97         for(int i = 0 ; i < res.size() ; i++) {
 98             for(int j = 0 ; j < res.size() ; j++) {
 99                 if((res[i] | res[j]) == ans) {
100                     cont++;
101                 }
102             }
103         }
104         printf("%d\n" , cont / 2 + 1);
105     }
106 }

 

posted @ 2016-03-30 21:37  Recoder  阅读(258)  评论(0编辑  收藏  举报