1. 程式人生 > >Wall Painting 2013ACM/ICPC亞洲區南京站現場賽 (組合數;位運算;找規律)

Wall Painting 2013ACM/ICPC亞洲區南京站現場賽 (組合數;位運算;找規律)

  • 題意:給你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; }