zoukankan      html  css  js  c++  java
  • lightoj 1215

    lightoj 1215 Finding LCM

    链接http://www.lightoj.com/volume_showproblem.php?problem=1215

    题意:已知 a, b, l 和 lcm(a, b, c) = l ,求最小的 c 的值。

    思路:先找 l 的素因子并判断此因子是否为 a, b 的素因子,如果是,则判断他们各自的欧拉值的大小。因为 c 最大可能等于 l 的值,所以刚开始先把 l 的值赋给 c 。 

      当 l 中的某个素因子的欧拉值(lr1)大于 a,b 中相同的素因子的欧拉值(ar1, br1)时,c中肯定含有次素因子并且欧拉值(cr1 >= lr1 ),然而 c 是 l 的因子,所以(cr1 <= lr1 ), 所以 cr1 == lr1 ,不用进行处理。

      当 l 中的某个素因子的欧拉值(lr1)等于(最大就是等于,不可能小于) a,b 中相同的素因子的欧拉值(ar1, br1)时,c中不一定含有次素因子,当 c 要取最小时,就可以不含有这个素因子,所以就把 c 中的 此素因子除干净。

    代码

     

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 typedef long long LL;
     7 const int N = 1002;
     8 bool tag[N];
     9 int prime[175];
    10 int k = 0;
    11 LL a, b ,c, l;
    12 
    13 LL stein(LL a, LL b) //stein 公式求最大公约数
    14 {
    15     if(a < b) swap(a, b);
    16     if(!b) return a;
    17     if(!(a&1) && !(b&1))    return 2* stein(a>>1, b>>1);
    18     if(!(a&1))  return stein(a>>1, b);
    19     if(!(b&1))  return stein(a, b>>1);
    20     return stein((a-b)>>1, b);
    21 }
    22 //当然,你也可以用欧几里得
    23 LL gcd(LL a, LL b)
    24 {
    25     return b ? gcd(b, a%b) : a;
    26 }
    27 
    28 int euler(LL *n, int m) //计算欧拉函数: 此函数中 n 值的变化会传回原处
    29 {
    30     int e = 0;
    31     while(!((*n) % m))
    32         e++, (*n) /= m;
    33     return e;
    34 }
    35 
    36 void prm()  //素数表(线性素数筛法)
    37 {
    38     int i,j;
    39     memset(tag, 0, sizeof(tag));
    40     tag[4] = 1, prime[k++] = 2;
    41     for(i = 3; i < N; i += 2)
    42     {
    43         if(!tag[i]) prime[k++] = i;
    44         for(j = 0; j < k && i*prime[j] < N; ++j)
    45         {
    46             tag[i*prime[j]] = 1;
    47             if(i%prime[j] == 0) break;
    48         }
    49     }
    50 }
    51 
    52 void ct(int q)   //计算c值
    53 {
    54     int i, cnta, cntb, cntL, cnt0, cs = 1;
    55     c = l;     // c 最大可能等于c, 先赋值为c,遇到情况在做除法减小它
    56     if(l % (a/stein(a,b)*b))    //不可能的情况:l 不是(a, b)的最小公倍数的倍数
    57     {
    58         printf("Case %d: impossible
    ", q);
    59         return;
    60     }
    61     for(i=0; i < k && (prime[i] <= a || prime[i] <= b); i++)    //
    62     {
    63         cnta = cntb = 0;
    64         if(!(l%prime[i]))   //是某个素数倍数的时候
    65         {
    66             cntL = euler(&l, prime[i]);     // l 部分欧拉函数值
    67             if(!(a%prime[i]))           // 当这个素数也是a 的因子的时候
    68                 cnta = euler(&a, prime[i]);     // a 的部分欧拉函数值
    69             if(!(b%prime[i]))       //当这个素数也是b 的因子的时候
    70                 cntb = euler(&b,prime[i]);  //同 a 的操作
    71             cnt0 = cnta > cntb ? cnta : cntb; // 最小公倍数当然是取值较大欧拉值
    72             /*
    73             a,b里边因子的欧拉值肯定要小于等于l的相同的因子的欧拉值的,当相等时,c要取最小就必须不含此因子
    74             当a, b 中的因子的欧拉值都小于l中的时,c中相同因子的欧拉值必须大于等于l中的值,最小当然取等于啦
    75             这也是为什么下面的只处理等于的情况
    76             */
    77             if(cntL == cnt0)    
    78                 while(cnt0--)   
    79                     c /= prime[i];
    80         }
    81     }
    82     if(a > 1 && euler(&l, a) <= 1)  c /= a;     //当 a 中含有大于1000的素数时的处理a
    83     if(b > 1 && euler(&l, b) <= 1)  c /= b;     //当 b 中含有大于1000的素数时的处理b
    84     printf("Case %d: %lld
    ", q, c);
    85 }
    86 
    87 int main()
    88 {
    89     int t, q=1;
    90     prm();
    91     scanf("%d", &t);
    92     while(t--)
    93     {
    94         scanf("%lld%lld%lld", &a, &b, &l);
    95         ct(q++);
    96     }
    97     return 0;
    98 }

     

     

     

  • 相关阅读:
    Java内存回收
    Android四大基本组件介绍与生命周期
    JAVA中获取当前系统时间
    jquery如何判断元素是否被点击_百度知道
    css控制div显示/隐藏方法及2种方法比较原码
    点击图标不断震动效果
    jquery 如何动态添加、删除class样式方法介绍_jquery_脚本之家
    HTML5绘制矩形和圆形并且还有获取在这个图层内的坐标的思路和代码
    Attribute name invalid for tag form according to TLD异常解决办法_gaigai_百度空间
    html5绘图
  • 原文地址:https://www.cnblogs.com/Duahanlang/p/3233445.html
Copyright © 2011-2022 走看看