zoukankan      html  css  js  c++  java
  • Luogu P5087 数学

    题意

    给定一个长度为 (n) 的序列 (a_i),求出在这个序列中所有选出 (k) 个元素方案中元素的乘积之和。

    ( exttt{Data Range:}1leq nleq 10^5,1leq kleq 300)

    题解

    多项式乘法。

    很明显答案为

    [[x^k]prodlimits_{i=1}^{n}(1+a_ix) ]

    来考虑一下证明。

    这些多项式乘积中 (x^k) 的系数相当于在 (n) 个多项式任意选出 (k) 个多项式,其中被选出来的的取一次项,剩下的取常数项,将这些东西乘起来的和。这个东西很明显是跟题目等价的。

    同时注意到每个多项式是一次多项式所以可以 (O(n)) 乘起来,总复杂度 (O(nk))

    考虑一个加强版,其中 (1leq nleq 5 imes 10^5,1leq kleq 5 imes10^5) 并且对 (998244353) 取模,这个时候剩下题解中的 DP 就基本上不能用了,而如果以多项式乘法的角度去思考的话发现这个东西可以分治 NTT,然后 (O(nlog^2n)) 就做完了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef int ll;
    typedef long long int li;
    const ll MAXN=2e5+51,MOD=1e9+7;
    ll n,kk,c,x;
    ll f[MAXN];
    inline ll read()
    {
        register ll num=0,neg=1;
        register char ch=getchar();
        while(!isdigit(ch)&&ch!='-')
        {
            ch=getchar();
        }
        if(ch=='-')
        {
            neg=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            num=(num<<3)+(num<<1)+(ch-'0');
            ch=getchar();
        }
        return num*neg;
    }
    int main()
    {
        n=read(),kk=read(),f[0]=1;
        for(register int i=1;i<=n;i++)
        {
            x=read();
            for(register int j=c;j>=0;j--)
            {
                f[j+1]=(f[j+1]+(li)f[j]*x%MOD)%MOD;
            }
            c=c==kk?kk:c+1;
        }
        printf("%d
    ",f[kk]);
    }
    
  • 相关阅读:
    appium python api(转)
    make clean 与 make distclean 的区别
    实参相依查找[条款25]----《C++必知必会》
    成员函数查找[条款24]---《C++必知必会》
    C++匿名名字空间
    程序界面多语言切换功能如何实现
    C 语言中 define 的全部使用方法总结
    #if defined(__cplusplus)
    伯乐在线
    jsp手动分页
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13884474.html
Copyright © 2011-2022 走看看