Wall Painting 2013ACM/ICPC亞洲區南京站現場賽 (組合數;位運算;找規律)
阿新 • • 發佈:2019-01-09
- 題意:給你n個整數,讓你找出任意(1~n)個數的異或值的和,並從1~n分別輸出
- 演算法:組合數;位運算;找規律
- 思路:先找到二進位制從0~63位的1的個數,當要找到任意 i 個數的異或值的和時,相當於在(1~63)位中每一位的1的個數中找出任意(1~k)(k<=i)個1,再用0補齊剩餘的(i-k)。
#include <bits/stdc++.h>
#define pi acos(-1)
#define fastcin ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1000 + 10;
const LL mod = 1e6 + 3;
LL a[maxn], cnt[100], C[maxn][maxn];
void init()
{
for(int i=0; i<maxn; i++){///////// i不能<=maxn ! 會越界!RE!
C[i][0] = 1%mod;
for (int j=1; j<i; j++){
C[i][j] = (C[i-1][j-1] + C[i-1][j])%mod;
}
C[i][i]=1%mod;
}
}
int main()
{
init();
int n;
while(scanf("%d", &n)!=EOF)
{
memset(cnt, 0, sizeof(cnt));
for(int i=0; i<n; i++){
scanf("%I64d", &a[i]);
for (int j=0; j<63 && (1<<j)<=a[i]; j++){
if(a[i]&(1<<j)) cnt[j]++;
}
}
for(int i=1; i<=n; i++){
LL ans =0;
for(int j=0; j<63; j++){
if(cnt[j]==0) continue;
for(int k=1; k<=i; k+=2){
if(cnt[j]>=k && (n-cnt[j])>=i-k){
ans += C[cnt[j]][k] * C[n-cnt[j]][i-k] %mod *(1LL<<j) %mod;
ans %= mod;
}
}
}
printf("%I64d", ans);
if(i!=n) printf(" ");
else puts("");
}
}
return 0;
}