北京区域赛I题,Uva7676,A Boring Problem,前缀和差分

转载自https://blog.csdn.net/weixin_37517391/article/details/83821752

题解

其实这题不难,只要想到了前缀和差分就基本OK了.
我们要求的是第$i$项的式子:
$F(i)=(a_1+a_2+...+a_i)^k+(a_2+...+a_i)^k+...+a_i^k$
记$S_i = a_1 + a_2 +...+a_i,S_0=0$
$F(i) = (S_i-S_0)^k+(S_i-S_1)^k+...+(S_i-S_{i-1})^k$
二项式定理展开:
$F(i) = \sum_{t=0}^kC_k^tS_i^t(-S_0)^{k-t} +  \sum_{t=0}^kC_k^tS_i^t(-S_1)^{k-t} +...+ \sum_{t=0}^kC_k^tS_i^t(-S_{i-1})^{k-t}$
整理得:
$F(i) = \sum_{t=0}^k C_k^t S_i^t(-1)^{k-t} (S_0^{k-t}+S_1^{k-t}+...+S_{i-1}^{k-t})$
再记:
$SS[i][j] = S_0^i + S_1^i + ... + S_j^i$
那么
$F(i) = \sum_{t=0}^k C_k^t S_i^t(-1)^{k-t} (SS[k-t][i-1])$
注意到$SS$可以$O(nk)$预处理出来,$S$也可以$O(nk)$预处理出来,而$F(i)$就可以$O(k)$出来。

代码

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #define pr(x) std::cout << #x << ':' << x << std::endl
 5 #define rep(i,a,b) for(int i = a;i <= b;++i)
 6 
 7 typedef long long LL;
 8 const int N = 100010;
 9 const LL P = 1e9+7;
10 int T,n,k;
11 char s[N];
12 long long S[101][N],SS[101][N];
13 long long C[110][110];
14 void init() {
15     C[0][0] = 1;
16     for(int i = 1;i <= 100;++i) {
17         C[i][0] = 1;
18         for(int j = 1;j <= i;++j) {
19             C[i][j] = (C[i-1][j-1] + C[i-1][j]) % P;
20         }
21     }
22 }
23 int main() {
24     std::ios::sync_with_stdio(false);
25     init();
26     std::cin >> T;
27     while(T--) {
28         std::cin >> n >> k;
29         std::cin >> s;
30         for(int i = 0;i <= n;++i) S[0][i] = 1;
31         for(int i = 1;i <= n;++i) S[1][i] = (s[i-1]-'0') + S[1][i-1] ;
32         for(int i = 2;i <= k;++i) 
33             for(int j = 1;j <= n;++j)
34                 S[i][j] = S[1][j] * S[i-1][j] % P;
35         
36         SS[0][0] = 1;   //特殊化处理,0^0=1
37 
38         for(int i = 0;i <= k;++i) {
39             for(int j = 1;j <= n;++j) 
40                 SS[i][j] = (SS[i][j-1] + S[i][j])% P;
41         }
42         
43         for(int i = 1;i <= n;++i) {
44             long long ans = 0;
45             for(int j = 0;j <= k;++j) {
46                 long long res = C[k][j]*S[j][i]%P*SS[k-j][i-1]%P;
47                 if((k-j)%2==0) ans = (ans + res) % P;
48                 else ans = (ans - res + P) % P;
49             }
50             if(i != 1) std::cout << " ";
51             std::cout << ans;
52         }
53         std::cout << std::endl;
54     }
55     return 0;
56 }

 

posted @ 2019-02-25 18:45  Rogn  阅读(388)  评论(0编辑  收藏  举报