Hackerrank--Emma and sum of products (FFT)

题目链接

Emma is really fond of integers and loves playing with them. Her friends were jealous, and to test her, one of them gave her a problem. 
Emma is given a list A of N integers and is asked a set of Q queries. Each query is denoted by an integer K, for which you have to return the sum of product of all possible sublists having exactly K elements. 
Emma has got stuck in this problem and you being her best friend have decided to help her write a code to solve it. Since the answers can be very large, print the answers modulo100003.

Input Format
First line has an integer N, denoting the number of integers in list A. Next line contains N space separated integers. The third line contains integer Q, and next Q lines have a single integer K.

Output Format
For each of the queries, print the corresponding answer in a new line.

NOTE Sublist here refers to selecting K elements from a list of N elements. There will be (NK) ways to do that, it doesn't matter if two elements are same.

Constraints
1N3×104 
1Ai105 
1QN 
1KN

Sample Input #00

3
1 2 3
2
1
2

Sample Output #00

6
11

Sample Input #01

3
1 2 2
1
2

Sample Output #01

8

Explanation

Sample #00: 
For K=1 possible sublists are {1},{2},{3} so answer is 1+2+3=6
For K=2 possible sublists are {1,2},{2,3},{3,1} so answer is (1×2)+(2×3)+(3×1)=2+6+3=11.

Sample #01: 
For K=2 possible sublists are {1,2},{2,2},{2,1} so answer is (1×2)+(2×2)+(2×1)=2+4+2=8.

题意:给出n个数,有q次询问,每次询问一个k,从n个数中选出k个数,对这k个数做乘积,求所有可能的选法的和。

我们把每个数看做一个多项式:x + A[i], 那么就可以得到n个这样的多项式。 将这n个多项式相乘,

那么k对应的查询的答案就是多项式中x^k项的系数,和母函数有点类似。

下面就是如何计算n个多项式的乘积,想到用FFT,但是不可以直接线性的计算这n个多项式的乘积,时间复杂度

太高,所以想到分治的思想,总的复杂度就是O(n*(log(n)^2))

Accepted Code:

  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include <string>
  3 #include <vector>
  4 #include <algorithm>
  5 #include <numeric>
  6 #include <set>
  7 #include <map>
  8 #include <queue>
  9 #include <iostream>
 10 #include <sstream>
 11 #include <cstdio>
 12 #include <cmath>
 13 #include <ctime>
 14 #include <cstring>
 15 #include <cctype>
 16 #include <cassert>
 17 #include <limits>
 18 #include <bitset>
 19 #include <complex>
 20 #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
 21 #define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
 22 #define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
 23 #define all(o) (o).begin(), (o).end()
 24 #define pb(x) push_back(x)
 25 #define mp(x,y) make_pair((x),(y))
 26 #define mset(m,v) memset(m,v,sizeof(m))
 27 #define INF 0x3f3f3f3f
 28 #define INFL 0x3f3f3f3f3f3f3f3fLL
 29 using namespace std;
 30 typedef vector<int> vi; typedef pair<int,int> pii; typedef vector<pair<int,int> > vpii;
 31 typedef long long ll; typedef vector<long long> vl; typedef pair<long long,long long> pll; typedef vector<pair<long long,long long> > vpll;
 32 typedef vector<string> vs; typedef long double ld;
 33 template<typename T, typename U> inline void amin(T &x, U y) { if(y < x) x = y; }
 34 template<typename T, typename U> inline void amax(T &x, U y) { if(x < y) x = y; }
 35 
 36 typedef long double Num;    //??????long double?????
 37 const Num PI = 3.141592653589793238462643383279L;
 38 typedef complex<Num> Complex;
 39 //n?????
 40 //a?????
 41 void fft_main(int n, Num theta, Complex a[]) {
 42     for(int m = n; m >= 2; m >>= 1) {
 43         int mh = m >> 1;
 44         Complex thetaI = Complex(0, theta);
 45         rep(i, mh) {
 46             Complex w = exp((Num)i*thetaI);
 47             for(int j = i; j < n; j += m) {
 48                 int k = j + mh;
 49                 Complex x = a[j] - a[k];
 50                 a[j] += a[k];
 51                 a[k] = w * x;
 52             }
 53         }
 54         theta *= 2;
 55     }
 56     int i = 0;
 57     reu(j, 1, n-1) {
 58         for(int k = n >> 1; k > (i ^= k); k >>= 1) ;
 59         if(j < i) swap(a[i], a[j]);
 60     }
 61 }
 62 
 63 void fft(int n, Complex a[]) { fft_main(n, 2 * PI / n, a); }
 64 void inverse_fft(int n, Complex a[]) { fft_main(n, -2 * PI / n, a); }
 65 
 66 void convolution(vector<Complex> &v, vector<Complex> &w) {
 67     int n = 1, vwn = v.size() + w.size() - 1;
 68     while(n < vwn) n <<= 1;
 69     v.resize(n), w.resize(n);
 70     fft(n, &v[0]);
 71     fft(n, &w[0]);
 72     rep(i, n) v[i] *= w[i];
 73     inverse_fft(n, &v[0]);
 74     rep(i, n) v[i] /= n;
 75 }
 76 
 77 const int MOD = 100003;
 78 
 79 vector<int> calc_dfs(const vector<int> &A, int l, int r) {
 80     if(r - l == 1) {
 81         vector<int> res(2);
 82         res[0] = 1;
 83         res[1] = A[l];
 84         return res;
 85     }
 86     int mid = (l + r) / 2;
 87     vector<int> L = calc_dfs(A, l, mid), R = calc_dfs(A, mid, r);
 88     vector<Complex> Lc(all(L)), Rc(all(R));
 89     convolution(Lc, Rc);
 90     int n = L.size() + R.size() - 1;
 91     vector<int> res(n);
 92     rep(i, n) res[i] = (long long)(Lc[i].real() + .5) % MOD;
 93 //    cerr << "["<< l << "," << r <<"): ";
 94 //    rep(i, n) cerr << res[i] << ", "; cerr << endl;
 95     return res;
 96 }
 97 
 98 int main() {
 99     int N;
100     scanf("%d", &N);
101     vector<int> A(N);
102     rep(i, N) {
103         scanf("%d", &A[i]);
104         A[i] %= MOD;
105     }
106     vector<int> ans = calc_dfs(A, 0, N);
107     int Q;
108     scanf("%d", &Q);
109     rep(ii, Q) {
110         int K;
111         scanf("%d", &K);
112         printf("%d\n", ans[K]);
113     }
114     return 0;
115 }

 

posted on 2014-08-19 08:58  Stomach_ache  阅读(337)  评论(0编辑  收藏  举报

导航