ZOJ 3870 Team Formation (The 12th Zhejiang Provincial Collegiate Programming Contest 数位DP+二分)

【题目链接】click here~~

【题目大意】给你一些数,每次选两个数a,b如果a,b的异或值大于a和b,则满足条件,求有多少种满足的

【解题思路】:数位DP+二分了,先把队友代码弱弱贴上(其实这到题翻译之后,全程我在打酱油,没有思路)明天好好研究~~

代码:

#include<stdio.h>
#include<string>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100005];
int n;

int shuru()
{
    int b;
    bool fushu=0;
    char ch;
    while(!((ch=getchar())>='0'&&ch<='9'))
    {
        if(ch=='-')
        {
            fushu=1;
            ch=getchar();
            break;
        }
    }
    b=(ch-'0');
    while((ch=getchar())>='0' && ch<='9')
        b=b*10+(ch-'0');
    return fushu? -b : b;
}
int jiao1[100],jiao2[100];
int main()
{
//    freopen("in.txt","r",stdin);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            a[i] = shuru();
        sort(a,a+n);
        long long sum=0;

        for(int i=0; i<=32; i++)
        {
            long long p=(long long) pow(2,i);
            jiao1[i]=lower_bound(a,a+n,p)-a;
        }
        for(int i=0; i<=32; i++)
        {
            long long p=(long long) pow(2,i);
            jiao2[i]=upper_bound(a,a+n,p-1)-a;
        }
        for(int i=n-1; i>=1; i--)
        {
            int top=0;
            int ans[40];
            int xx=a[i];
            while(xx)
            {
                ans[top++]=xx%2;
                xx/=2;
            }
            for(int j=top-1; j>=0; j--)
            {
                if(!ans[j])
                {
//                    printf("!%d!\n",a[i]);
                    int r=jiao2[j+1];
                    r-=1;
                    int l=jiao1[j];
                    sum+=r-l+1;
//                    printf("%d %d\n",l,r);
                }
            }
        }
        printf("%lld\n",sum);
    }
}


你可能感兴趣的:(ACM,比赛题)