zoukankan      html  css  js  c++  java
  • Vivian's Problem UVA

    借鉴:https://blog.csdn.net/miku23736748/article/details/52135932

    https://blog.csdn.net/acm_cxlove/article/details/7860735

    题意:给定k个数,然后为每个数添加一个幂ei(0=<ei<=10),最后k项累乘的结果为M,如果M的所有因子的和可以写成2^x,求x的最大值,如果没有条件满足,输出NO

    我们把满足 E = 2 ^ i - 1 的数称为梅林数  E如果是素数则为梅森素数。

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

    并且这个2的幂(指数)正好等于作为因子的梅森素数的梅森指数的和

    而  3 (2的2次幂-1) X 7 (2的3次幂-1) = 21;

    21的因数和1+3+7+21=32=2^5;  这个  2的幂 5 = 2 + 3;

    所以本题的解题思路就出来了

    对于每一个输入的数  我们去判断是否为几个不重复的梅林素数的乘积组成的

    如果不是则把这个数的e置为0  所以就不用考虑它了 

    如果是 我们就用二进制去记下它是由那几个梅林素数组成的  这里我们记下的是梅林素数在数组中的下标  也是对应梅林素数的梅林指数在相应数组中的下标 因为都一一对应

    然后我们遍历这些这些下标。。。用dp数组标记这些下标  和  可以由这些下标组成的另一些下标 而且这另一些下标还得必须是输入的那几个数所产生的  

    这句话什么意思呢。。。就是看看组成输入的这几个数的梅林素数是否有重复  没有就合并

    最后通过标记 累加梅林素数的梅林指数 求出最大值即可

    #include <iostream>
    #include <cstdio>
    #include <sstream>
    #include <cstring>
    #include <map>
    #include <set>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #define MOD 2018
    #define LL long long
    #define ULL unsigned long long
    #define Pair pair<int, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define _  ios_base::sync_with_stdio(0),cin.tie(0)
    //freopen("1.txt", "r", stdin);
    using namespace std;
    const int maxn = 10010, INF = 0x7fffffff;
    int mason[8]={3,7,31,127,8191,131071,524287,2147483647};  //梅林素数
    int ans[8]={2,3,5,7,13,17,19,31};   //梅林素数对应的梅林指数
    int dp[1<<8];
    
    int check(int k)
    {
        int cnt = 0;
        for(int i=0; i<8; i++)
        {
            if(k % mason[i] == 0)
            {
                cnt |= 1<<i;
                k /= mason[i];
            }
            if(k % mason[i] == 0)
            {
                return 0;
            }
        }
        if(k > 1)
            return 0;
        return cnt;
    }
    
    int cal(int x)
    {
        int res = 0;
        for(int i=0; i<8; i++)
            if(x & (1<<i))
                res += ans[i];
        return res;
    }
    
    int main()
    {
        int n, a[1000];
        while(~scanf("%d",&n))
        {
            mem(a, 0);
            mem(dp, 0);
            for(int i=0; i<n; i++)
            {
                int w;
                scanf("%d",&w);
                int temp = check(w);
                if(!temp) i--, n--;
                else a[i] = temp;
            }
            if(n == 0)
            {
                cout<< "NO" <<endl;
                continue;
            }
            dp[0] = 1;
            for(int i=0; i<n; i++)
                for(int j=0; j< 1<<8; j++)
                    if(!(j & a[i]))     //判断两个数的梅林素数是否重复
                        dp[j|a[i]] |= dp[j];  //j|a[i] 第一次是否被标记却决于dp[j] 因为a[i]肯定有 但不知道j是否有 这样想 = 就可以 但为什么是 |= ,以为如果另一对j|a[i]的值与这对相同 而这对的j存在 另一对的j不存在 如果是=就会被置为零 所以用|=
            int maxx = -INF;
            for(int i=0; i< 1<<8; i++)
            {
                if(dp[i])
                    maxx = max(maxx, cal(i));
    
            }
            cout<< maxx <<endl;
    
        }
    
    
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    java-继承的注意事项
    java-代码块-局部代码块、构造代码块、静态代码块
    java-源文件中可以有多个类,但是最多只能有一个public修饰
    java-权限修饰符的区别
    APP测试-adb简介
    APP测试-Android模拟器
    APP测试-SDK环境 for Windows
    自动化测试-流程
    接口测试-接口请求关联
    接口测试-moco+excel+requests框架
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9333910.html
Copyright © 2011-2022 走看看