【NOIP模拟题】【数学归纳法】【容斥原理】2016.11.18 第一题 信 题解

第一题:信(believe.cpp/c/pas)

背景描述:
一切死亡都有冗长的回声
—— 《一切》北岛
给定一个N个元素的序列A,
定义Bi = (Ai and A1) + (Ai and A2) + (Ai and A3)+ …… + (Ai and An)
定义Ci = (Ai or A1) + (Ai or A2) + … + (Ai or An)
求B和C序列。
输入格式:
第一行一个整数N表示序列长度
接下来一行N个整数, 第i个整数为Ai
输出格式:
第一行N个整数输出B序列
第二行N个整数输出C序列
样例输入:
4
3 5 1 1
样例输出:
6 8 4 4
16 22 10 10
数据规模:
对于50%的数据, N <= 1000
对于100%的数据, N <= 100000, Ai <= 100000
注意事项:
输入量较大, 请使用比较快的例如scanf的读入方式, 最好不要采用cin。

这道题嘛,水题,也有高端做法比如容斥原理。
A+B = A&B+A|B
但是就发最简单的。
em,输入量比较大,所以我不用scanf。让我们用一下读入优化。

附代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#define clr(a,x)  memset(x,a,sizeof(x))
#define ll long long
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif

using namespace std;

const int maxn = 100010;
ll a,n;
ll num[21],cnt[21],s[maxn],C[maxn],B[maxn];

template <class T> inline void read(T &xx)
{
    xx = 0;
    T flag = 1;
    char ch = (char)getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch == '-') flag = -1;
        ch = (char)getchar();
    }
    while(ch>='0' && ch<='9')
    {
        xx = (xx<<1) + (xx<<3) + ch - '0';
        ch = (char)getchar();
    }
    xx *= flag;
}

ll power(ll a, ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b%2 == 1)
            ans = ans * a;
        a = a*a;
        b /= 2;
    }
    return ans;
}

int main()
{
    freopen("believe.in","r",stdin);
    freopen("believe.out","w",stdout);
    read(n);
    for (ll i = 1; i <= n; i++)
    {
        read(a);
        for (ll j = 0; j <= 17; j++)
        {
            if((1<<j) & a) num[j]++;
            else cnt[j]++;
        }
        s[i] = a;
    }
    for (ll i = 1; i <= n; i++)
    {
        for (ll j = 0; j <= 17; j++)
            if((1<<j) & s[i])
                B[i] += power(2, j) * (num[j]);
        printf(AUTO" ",B[i]);
    } 
    printf("\n");
    for (ll i = 1; i <= n; i++)
    {
        for (ll j = 0; j <= 17; j++)
            if((1<<j) & s[i]) 
                C[i] += power(2, j) * (num[j]+cnt[j]);
            else
                C[i] += power(2, j) * (num[j]);
        printf(AUTO" ",C[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值