bnu1065(数位dp)

题意:
#include<stdio.h>
int main()
{
   int n,a[10001];
   int T;
   int i,j,k;
   int ans=0;
   scanf("%d",&T);
   while(T--)
   {
       scanf("%d",&n);
       ans=0;
       for(i=0;i<n;++i)
           scanf("%d",&a[i]);
       for(i=0;i<n;++i)
           for(j=0;j<n;++j)
               ans+=(a[i]|a[j]);
       printf("%d\n",ans);
   }
return 0;
}

将以上代码优化不超时。

题意就是这么简单

题解:
很巧妙的算法,利用数位dp的思想将位数分开计算,词穷无法描素,具体看代码。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
typedef long long lld;
#define oo 0x3f3f3f3f
#define maxn 10005
int is_one[maxn][20];//is_one[i][j]第i个数位数为j是1的个数
int sum[maxn];//sum[i]位数为i的和
int a[maxn];

int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        memset(sum,0,sizeof sum);
        memset(is_one,0,sizeof is_one);
        for(int i=1;i<=n;i++)
        {
            int t=a[i];
            for(int j=0;j<16;j++)
            {
                int r=t%2;
                if(r)
                {
                    sum[j]++;
                    is_one[i][j]=1;
                }
                t/=2;
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<16;j++)
            {
                if(is_one[i][j])
                    ans+=n*(1<<j);
                else
                    ans+=sum[j]*(1<<j);
            }
        }
        printf("%d\n",ans);
    }
	return 0;
}


你可能感兴趣的:(dp,BNU)