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] = ‘\0‘;
            cin >> ch;
            int cnt = 0;
            for(int j = 0;j <= 31;j++){
                if(ch[j] != ‘\0‘) 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;
}
 
时间: 2024-08-03 21:56:03

csuoj-1720-How to Get 2^n的相关文章

csuoj 1392: Number Trick

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1392 1392: Number Trick Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 200  Solved: 36[Submit][Status][Web Board] Description Input Output Sample Input 2.6 Sample Output 135 270 135135 270270 HINT 分析:

CSUOJ 1010 Water Drinking

Description The Happy Desert is full of sands. There is only a kind of animal called camel living on the Happy Desert. ‘Cause they live here, they need water here. Fortunately, they find a pond which is full of water in the east corner of the desert.

CSUOJ 1217 奇数个的那个数

Description 给定些数字,这些数中只有一个数出现了奇数次,找出这个数. Input 每组数据第一行n表示数字个数,1 <= n <= 2 ^ 18 且 n % 2 == 1. 接下来n行每行一个32位有符号整数. Output 出现奇数次那个数,每组数据对应一行. Sample Input 5 1 1 2 2 3 7 1 2 1 2 2 3 3 Sample Output 3 2 看了大神的代码 使用位运算o(╯□╰)o 1 # include <stdio.h> 2 i

Aizu 2164 CSUOJ 1436 Revenge of the Round Table

dp套一个burnside的壳子核心还是dpdp[i]表示有i个循环节时的染色方案数注意在dp的时候,不需要考虑重构的问题因为burnside会解决重构的问题dpA[i][j]表示以A开头,长度为i,结尾为j个A的合法方案数dpB[i][j]表示以B开头,长度为i,结尾为j个A的合法方案数接下来我们用dpA,dpB来计算dp[i]显然对于所有的dpB[i][1~k]都是满足dp[i]的因为它表示以B开头,以A结尾的染色方案,且结尾没有超过k个另外还有一部分就是以A开头的了假设我们在整个串的最前面

csuoj 1511: 残缺的棋盘

http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1511 1511: 残缺的棋盘 时间限制: 1 Sec  内存限制: 128 MB 题目描述 输入 输入包含不超过10000 组数据.每组数据包含6个整数r1, c1, r2, c2, r3, c3 (1<=r1, c1, r2, c2, r3, c3<=8). 三个格子A, B, C保证各不相同. 输出 对于每组数据,输出测试点编号和最少步数. 样例输入 1 1 8 7 5 6 1 1 3 3

CSUOJ 1343

1343: Long Long Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 180  Solved: 48[Submit][Status][Web Board] Description 现在有两个单调递增序列,第一个序列有N个整数,第二个序列有M个整数,现在你可以从第一个序列中选一个数x,然后从第二个序列中选一个数y,那么有多少种情况满足x+y<=K呢? Input 输入包含多组数据.    对于每组测试数据,第一行包含两个整数N, M , K 

并查集--CSUOJ 1601 War

并查集的经典题目: CSUOJ 1601: War Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 247  Solved: 70[Submit][Status][Web Board] Description AME decided to destroy CH’s country. In CH’ country, There are N villages, which are numbered from 1 to N. We say two vill

CSUOJ 1256 天朝的单行道

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1256 题目大意: 在另一个平行宇宙中,有一个神奇的国度名叫天朝.天朝一共有N个城市(标号分别为1, 2, …, N),M条道路,为了方便交通管制,天朝的M条道路都是单行道. 不久前天朝大选,小Q当选了天朝的总统.小Q家住在城市1,但天朝的办公地点在城市N,于是为了便于工作,小Q决定举家从城市1搬迁到城市N去居住.然而小Q惊奇的发现,现在并不存在从城市1出发到城市N路线. 但这点难题是无

CSUOJ 1858 Biorhythms 中国剩余定理

1858: Biorhythms Submit Page   Summary   Time Limit: 1 Sec     Memory Limit: 256 Mb     Submitted: 69     Solved: 37 Description Some people believe that there are three cycles in a person's life that start the day he or she is born. These three cycl

CSUOJ 1854 Refrigerator Magnets

1854: Refrigerator Magnets Submit Page   Summary   Time Limit: 2 Sec     Memory Limit: 256 Mb     Submitted: 96     Solved: 23 Description Like many families with small children, my family's refrigerator is adorned with a set of alphabet magnets: 26