• csuoj-1720-How to Get 2^n


    题目:

    Description

    Johnson is very interested in the k-th power of 2 number, such as 2,4,8,16 ....

    So he always boasts that he is good at solving problems with the power of two.

    One day, Alice could not stand Johnson’s bragging, and she come up a question to heckle him,

    Alice gave Johnson n numbers, and let Johnson takes two numbers inside guaranteeing sum of them is power of 2. Finally Alice let Johnson tell her how many methods can he get two valid numbers.

    Because Alice is goddess in Johnson’s heart , so he do not want to lose face in front of her . But he is very tight facing to his goddess , he hope you can help him solve this problem

    Input

    The first line contains an integer T (T<=2), means there are T test cases.

    For each case

    The first line contains an integer n, means there are n numbers.

    (1<=n<=100000)

    The next line contains n integers(v0,v1.....vn-1) (1<=vi<=10^30 , 2^100 approximately equal 10^30)

    Output

    Each case output the number of method.

    Sample Input

    1
    5
    3 2 5 4 1

    Sample Output

    2
    分析:
    1,打表求出2的K次方(k从1到100);
    2,输入数据,将大数从小到大排序,合并相同的数,并记录相同的个数;
    3,对于每个大数,分别对2的k次方用二分法求出对应的另一个大数,如果相同,则加上该数数目 * (该数数目 - 1) / 2,否则加上两数数目乘积。

    代码:
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int goal[100][31];
    struct BigNum{
        long long cnt;
        int num[31];
    }bigNum[100000];
    
    int cmp(const struct BigNum &a,const struct BigNum &b){
        for(int i = 0;i < 31;i++){
            if(a.num[i] > b.num[i]) return 0;
            else if(a.num[i] < b.num[i]) return 1;
        }
        return 1;
    }
    
    void init(){
        goal[0][30] = 2;
        for(int i = 1;i < 100;i++){
            for(int j = 30;j >= 0;j--){
                int x = goal[i - 1][j] * 2;
                goal[i][j] += x % 10;
                if(j > 0) goal[i][j - 1] = x / 10;
            }
        }
    }
    
    int same(int *a,int *b){
        for(int i = 0;i < 31;i++){
            if(a[i] > b[i]) return 1;
            else if(a[i] < b[i]) return -1;
        }
        return 0;
    }
    
    int find(int *ar,struct BigNum *temp,int b,int cnt){
        int begin = b;
        int end = cnt - 1;
        int middle = (begin + end) / 2;
        while(begin <= end){
            int result = same(ar,temp[middle].num);
            if(result == 0) return middle;
            else if(result == 1){
                begin = middle + 1;
                middle = (begin + end) / 2;
            }
            else{
                end = middle - 1;
                middle = (begin + end) / 2;
            }
        }
        return -1;
    }
    
    int main(){
        int t;
        cin >> t;
        init();
        while(t--){
            int n;
            cin >> n;
            for(int i = 0;i < n;i++){
                char ch[32];
                for(int j = 0;j <= 31;j++) ch[j] = '';
                cin >> ch;
                int cnt = 0;
                for(int j = 0;j <= 31;j++){
                    if(ch[j] != '') cnt++;
                    else break;
                }
                int index = 0;
                for(int j = 31 - cnt;j <= 30;j++) bigNum[i].num[j] = ch[index++] - '0';
                for(int j = 0;j < 31 - cnt;j++) bigNum[i].num[j] = 0;
            }
            sort(bigNum,bigNum + n,cmp);
            for(int i = 0;i < n;i++) bigNum[i].cnt = 1;
            struct BigNum *temp = new struct BigNum[n];
            int cnt = 0;
            int last[31];
            for(int i = 0;i < 31;i++) temp[cnt].num[i] = last[i] = bigNum[0].num[i];
            temp[cnt].cnt = 1;
            cnt++;
            for(int i = 1;i < n;i++){
                int result = same(last,bigNum[i].num);
                if(result == 0) {
                    temp[cnt - 1].cnt++;
                }
                else{
                    for(int j = 0;j < 31;j++) last[j] = temp[cnt].num[j] = bigNum[i].num[j];
                    temp[cnt].cnt = 1;
                    cnt++;
                }
            }
            long long res = 0;
            for(int i = 0;i < cnt;i++){
                for(int j = 0;j < 100;j++){
                    int flag = same(temp[i].num,goal[j]);
                    if(flag == -1){
                        int big[31];
                        int chu[31];
                        for(int k = 0;k < 31;k++) chu[k] = 0;
                        for(int k = 0;k < 31;k++) big[k] = goal[j][k];
                        for(int k = 30;k >= 0;k--){
                            if(big[k] >= temp[i].num[k])
                                chu[k] = big[k] - temp[i].num[k];
                            else{
                                chu[k] = big[k] + 10 - temp[i].num[k];
                                big[k - 1]--;
                            }
                        }
                        int index = find(chu,temp,i,cnt);
                        if(index != -1){
                            if(index == i) res += temp[index].cnt * (temp[index].cnt - 1) / 2;
                            else res += temp[index].cnt * temp[i].cnt;
                        }
                    }
                }
            }
            cout << res << endl;
        }
        return 0;
    }
     
  • 相关阅读:
    原笔迹手写实现平滑和笔锋效果之:笔迹的平滑(二)
    区块链入门(4)Truffle创建项目,编译,及项目部署
    github的基本使用
    ES6新特性之傻瓜式说明
    webpack之傻瓜式教程及前端自动化入门
    查找树莓派ip地址的常用方法
    树莓派的无屏幕安装的教程
    采用QHD分辨率使用kinect2_calibration,完成QHD图像校正
    编译ORBSLAM2 build_ros.sh,实现kinect2在ROS环境下运行ORBSLAM2
    重写kinect2_viewer,编译高博kinect2在orbslam2上跑的程序(解决cmakefile中库依赖和头文件的问题)
  • 原文地址:https://www.cnblogs.com/tracy520/p/6706978.html
Copyright © 2020-2023  润新知