• 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 }
  • 相关阅读:
    HANDLE CreateThread()
    偷懒的一天-jQuery之事件与应用
    web进阶之jQuery操作DOM元素&&MySQL记录操作&&PHP面向对象学习笔记
    无聊的周五晚上
    闲里偷闲
    被蚊子和自己搞毁的一天
    数据库有点意思
    周一周一周。。一
    无聊到周六的教研室
    1.Nginx相关概念
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4811962.html
Copyright © 2020-2023  润新知