zoukankan      html  css  js  c++  java
  • POJ 1777 mason素数

     题目大意:

    给定数列 a1 , a2 , ... , an

    希望找到一个  N = sigma(ai^ki)  , (0<=ki<10) ,ki可随自己定为什么

    只要保证N的因子和可以表示为 2^t的形式 , 输出t , 找不到就输出 NO

    关于梅森素数,有一个重要的定理:“一个数能够写成几个不重复的梅森素数的乘积” 等价于 “这个数的约数和是2的幂次”,但是不能重复,比如说3是梅森素数,9就不满足约数和为2的幂。

    还有一个重要内容就是,N的约数和幂次是可以直接由构成它的梅森素数的来源幂次相加而得的。

    “一个数能够写成几个不重复的梅森素数的乘积” 等价于 “这个数的约数和是2的幂次” 因为这两个概念是充分必要的

    那么就说明在这里要找到一个N表示为几个梅森素数的乘积,那么很明显,这里的ki只能是 0或者1 , 因为只要乘方了,那么必然那个数要么无法用梅森素数的乘积表示

    要么乘积中存在重复的梅森素数

    这里数字小于 2^31 , 在这个范围内只有 8个梅森素数

    一个个枚举跑一遍就行了,最后结合得到答案,可以利用简单的dp背包的思想

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <vector>
     4 #include <queue>
     5 #include <iostream>
     6 #include <set>
     7 using namespace std;
     8 #define pii pair<int,int>
     9 const int p[8] = {2,3,5,7,13,17,19,31}; //mason数的p的位置,表示为2^p-1
    10 int mason[9] , len[(1<<9)] , rec[(1<<9)] , tot;
    11 bool vis[(1<<9)];
    12 set<int> st;
    13 
    14 int Mason(int b){return (1<<b)-1;}
    15 
    16 void get_mason(){for(int i=0 ; i<8 ; i++)mason[i] = Mason(p[i]);}
    17 
    18 void init()
    19 {
    20     int all = (1<<8);
    21     for(int i=0 ; i<all ; i++){
    22         int t = 0;
    23         for(int j=0 ; j<8 ; j++)
    24             if(i&(1<<j)) t+=p[j];
    25         len[i] = t;
    26     }
    27 }
    28 
    29 int ok(int x)
    30 {
    31     int cur = 0;
    32     for(int i=0 ; i<8 ; i++){
    33         if(x%mason[i]==0){
    34             x /= mason[i];
    35             cur|=(1<<i);
    36         }
    37     }
    38     if(x>1) cur = 0;
    39     return cur;
    40 }
    41 
    42 int main()
    43 {
    44    // freopen("a.in" , "r" , stdin);
    45     get_mason();
    46     init();
    47     int n , a;
    48     while(~scanf("%d" , &n)){
    49         st.clear();
    50         for(int i=0 ; i<n ; i++){
    51             scanf("%d" , &a);
    52             int state = ok(a);
    53             if(state) st.insert(state);
    54         }
    55 
    56         memset(vis , 0 , sizeof(vis));
    57         tot = 0;
    58         set<int>::iterator it=st.begin();
    59         for( ; it!=st.end() ; it++) rec[tot++] = *it;
    60         int all = (1<<8);
    61         vis[0] = true;
    62         for(int i=0 ; i<tot ; i++){
    63             for(int j=all-1 ; j>=rec[i] ; j--)
    64                 if((rec[i]&j) == rec[i]) vis[j] = vis[j-rec[i]] | vis[j];
    65         }
    66         int ret = 0;
    67         for(int j=0 ; j<all ; j++)
    68             if(vis[j]) ret = max(ret , len[j]);
    69         if(ret) printf("%d
    " , ret);
    70         else puts("NO");
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    你可能不知道的js -- 数据类型转换
    项目开发过程中使用工具的相关配置 -- git / svn / 谷歌跨域
    博客园个人博客页面主题
    keep-alive指定条件缓存的坑
    element的多文件上传
    谷歌应用商店扩展程序
    从郭建的遭遇(自称最惨的创业者)看‘程序员的人生观’(一)
    我深表遗憾
    入门学习三
    编程入门学习二
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4811962.html
Copyright © 2011-2022 走看看