1. 程式人生 > >【XSY2032】簡單粗暴的題目 組合數

【XSY2032】簡單粗暴的題目 組合數

sca online line end string align for ret pan

題目描述

  給你\(n,k,a_1\ldots a_n\),設
\[ ans_n=\sum_{i=1}^n{(\sum_{j=i}^ns(j))}^k\\]
  求\(ans_1\ldots ans_n\)

  對\({10}^9+7\)取模

  \(n\leq 50000,k\leq 100\)

題解

  大水題

  這題就是在搞笑

  題解的做法是\(O(nk\log k)\)

  隨便推推就能推出\(O(nk)\)的做法
\[ \begin{align} ans_n&=\sum_{i=1}^n{(\sum_{j=i}^ns(j))}^k\&=\sum_{i=1}^n{(s_n-s_{i-1})}^k\&=\sum_{i=1}^n\sum_{j=0}^k{s_n}^{j}{s_{i-1}}^{k-j}{(-1)}^{k-j}\binom{k}{j}\&=\sum_{i=0}^k{s_n}^i{(-1)}^{k-i}\binom{k}{i}\sum_{j=1}^n{s_{j-1}}^{k-i} \end{align} \]

  維護最後那項即可。

  時間復雜度:\(O(nk)\)

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll p=1000000007;
ll c[110][110];
ll a[50010];
ll s[50010];
ll b[50010];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("xsy2032.in","r",stdin);
    freopen("xsy2032.out"
,"w",stdout); #endif int n,k; scanf("%d%d",&n,&k); int i,j; memset(c,0,sizeof c); for(i=0;i<=k;i++) { c[i][0]=1; for(j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%p; } b[0]=1; s[0]=1; for(i=1;i<=n;i++) { scanf("
%lld",&a[i]); a[i]=(a[i]+a[i-1])%p; for(j=1;j<=k;j++) b[j]=b[j-1]*a[i]%p; ll ans=0; for(j=0;j<=k;j++) ans=(ans+b[j]*s[k-j]%p*c[k][j]%p*((k-j)&1?-1:1))%p; ans=(ans+p)%p; printf("%lld\n",ans); for(j=0;j<=k;j++) s[j]=(s[j]+b[j])%p; } return 0; }

【XSY2032】簡單粗暴的題目 組合數