日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【2022 CCPC 华为云计算挑战赛】1005 带权子集和 (NTT 优化dp)

發(fā)布時間:2024/1/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【2022 CCPC 华为云计算挑战赛】1005 带权子集和 (NTT 优化dp) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接:

https://acm.hdu.edu.cn/contest/problem?cid=1072&pid=1005

題意:

給定大小為 n n n的可重集 A A A,給定非負整數(shù) k , x k,x k,x。對于 A A A的一個非空子集 S S S,設 s u m ( S ) sum(S) sum(S)為集合 S S S的元素權值之和, ∣ S ∣ |S| S為集合 S S S的元素個數(shù)。求 ∑ S ? A , S ≠ ? s u m ( S ) k ? x ∣ S ∣ \sum_{S\subseteq A,S \neq \varnothing}sum(S)^k \cdot x^{|S|} S?A,S=??sum(S)k?xS 998244353 998244353 998244353取模的結果。

算法:

NTT優(yōu)化dp。

時間復雜度:

O ( n k l o g ( k ) ) O(nklog(k)) O(nklog(k))

解法:

為了便于理解,我們先設 d p i , j , l dp_{i,j,l} dpi,j,l?表示為前 i i i個,選 j j j個作為子集,在 l l l次冪下的答案。
p p p為前 i ? 1 i-1 i?1個數(shù)中任選 j ? 1 j-1 j?1個數(shù)的和, P P P為所有情況的 p p p的集合, P = { p 0 , p 1 , p 2 , . . . } P=\{p_0,p_1,p_2,...\} P={p0?,p1?,p2?,...}

根據(jù)題意,可以得出前 i ? 1 i-1 i?1個,選 j ? 1 j-1 j?1個作為子集,在 l l l次冪下的答案 d p i ? 1 , j ? 1 , l = ( p 0 l + p 1 l + p 2 l + . . . ) x j ? 1 dp_{i-1,j-1,l}=(p_0^l+p_1^l+p_2^l+...)x^{j-1} dpi?1,j?1,l?=(p0l?+p1l?+p2l?+...)xj?1

s u m l = p 0 l + p 1 l + p 2 l + . . . sum_l=p_0^l+p_1^l+p_2^l+... suml?=p0l?+p1l?+p2l?+...,可得 d p i ? 1 , j ? 1 , l = s u m l x j ? 1 dp_{i-1,j-1,l}=sum_l x^{j-1} dpi?1,j?1,l?=suml?xj?1

考慮狀態(tài)轉移,考慮選 a i a_i ai?給答案帶來的變化:

d p i , j , l = [ ( p 0 + a i ) l + ( p 1 + a i ) l + ( p 2 + a i ) l + . . . ] x j = [ ( l 0 ) a i l s u m 0 + ( l 1 ) a i l ? 1 s u m 1 + ( l 2 ) a i l ? 2 s u m 2 + . . . + ( l l ) a i 0 s u m l ] x j = [ ( l 0 ) a i l d p i ? 1 , j ? 1 , 0 + ( l 1 ) a i l ? 1 d p i ? 1 , j ? 1 , 1 + ( l 2 ) a i l ? 2 d p i ? 1 , j ? 1 , 2 + . . . + ( l l ) a i 0 d p i ? 1 , j ? 1 , l ] x = [ 1 0 ! ( l ? 0 ) ! a i l d p i ? 1 , j ? 1 , 0 + 1 1 ! ( l ? 1 ) ! a i l ? 1 d p i ? 1 , j ? 1 , 1 + 1 2 ! ( l ? 2 ) ! a i l ? 2 d p i ? 1 , j ? 1 , 2 + . . . + 1 l ! ( l ? l ) ! a i 0 d p i ? 1 , j ? 1 , l ] x l ! \begin{aligned} dp_{i,j,l}&=[(p_0+a_i)^l+(p_1+a_i)^l+(p_2+a_i)^l+...]x^j\\ &=[\binom{l}{0} a_i^l sum_0+\binom{l}{1} a_i^{l-1} sum_1+\binom{l}{2} a_i^{l-2} sum_2+...+\binom{l}{l} a_i^0 sum_l]x^j\\ &=[\binom{l}{0} a_i^l dp_{i-1,j-1,0}+\binom{l}{1} a_i^{l-1} dp_{i-1,j-1,1}+\binom{l}{2} a_i^{l-2} dp_{i-1,j-1,2}+...+\binom{l}{l} a_i^0 dp_{i-1,j-1,l}]x\\ &=[\frac{1}{0!(l-0)!} a_i^l dp_{i-1,j-1,0}+\frac{1}{1!(l-1)!} a_i^{l-1} dp_{i-1,j-1,1}+\frac{1}{2!(l-2)!} a_i^{l-2} dp_{i-1,j-1,2}+...+\frac{1}{l!(l-l)!} a_i^0 dp_{i-1,j-1,l}]x l! \end{aligned} dpi,j,l??=[(p0?+ai?)l+(p1?+ai?)l+(p2?+ai?)l+...]xj=[(0l?)ail?sum0?+(1l?)ail?1?sum1?+(2l?)ail?2?sum2?+...+(ll?)ai0?suml?]xj=[(0l?)ail?dpi?1,j?1,0?+(1l?)ail?1?dpi?1,j?1,1?+(2l?)ail?2?dpi?1,j?1,2?+...+(ll?)ai0?dpi?1,j?1,l?]x=[0!(l?0)!1?ail?dpi?1,j?1,0?+1!(l?1)!1?ail?1?dpi?1,j?1,1?+2!(l?2)!1?ail?2?dpi?1,j?1,2?+...+l!(l?l)!1?ai0?dpi?1,j?1,l?]xl!?

我們發(fā)現(xiàn)化簡到最后,參數(shù) j j j并沒有參與計算,因此可將式子轉化為
d p i , l = [ 1 0 ! l ! a i l d p i ? 1 , 0 + 1 1 ! ( l ? 1 ) ! a i l ? 1 d p i ? 1 , 1 + 1 2 ! ( l ? 2 ) ! a i l ? 2 d p i ? 1 , 2 + . . . + 1 l ! 0 ! a i 0 d p i ? 1 , l ] x l ! dp_{i,l}=[\frac{1}{0!l!} a_i^l dp_{i-1,0}+\frac{1}{1!(l-1)!} a_i^{l-1} dp_{i-1,1}+\frac{1}{2!(l-2)!} a_i^{l-2} dp_{i-1,2}+...+\frac{1}{l!0!} a_i^0 dp_{i-1,l}]x l! dpi,l?=[0!l!1?ail?dpi?1,0?+1!(l?1)!1?ail?1?dpi?1,1?+2!(l?2)!1?ail?2?dpi?1,2?+...+l!0!1?ai0?dpi?1,l?]xl!

我們可以發(fā)現(xiàn)這就是個多項式乘法。

F ( u ) = 1 0 ! d p i ? 1 , 0 u 0 + 1 1 ! d p i ? 1 , 1 u 1 + 1 2 ! d p i ? 1 , 2 u 2 + . . . + 1 l ! d p i ? 1 , l u l F(u)=\frac{1}{0!} dp_{i-1,0}u^0+\frac{1}{1!} dp_{i-1,1}u^1+\frac{1}{2!} dp_{i-1,2}u^2+...+\frac{1}{l!} dp_{i-1,l}u^l F(u)=0!1?dpi?1,0?u0+1!1?dpi?1,1?u1+2!1?dpi?1,2?u2+...+l!1?dpi?1,l?ul

G ( u ) = 1 0 ! a i 0 u 0 + 1 1 ! a i 1 u 1 + 1 2 ! a i 2 u 2 + . . . + 1 l ! a i l u l G(u)=\frac{1}{0!} a_i^0 u^0+\frac{1}{1!} a_i^1 u^1+\frac{1}{2!} a_i^2 u^2+...+\frac{1}{l!} a_i^l u^l G(u)=0!1?ai0?u0+1!1?ai1?u1+2!1?ai2?u2+...+l!1?ail?ul

H ( u ) = F ( u ) G ( u ) x l ! H(u)=F(u)G(u)xl! H(u)=F(u)G(u)xl!

那么 d p i , l = d p i ? 1 , l + a i l x + [ u l ] H dp_{i,l}=dp_{i-1,l}+a_i^lx+[u^l]H dpi,l?=dpi?1,l?+ail?x+[ul]H [ u l ] H [u^l]H [ul]H表示 H ( u ) H(u) H(u)的第 l l l項系數(shù)),最終答案為 d p n , k dp_{n,k} dpn,k?

#include<bits/stdc++.h> #define ll long long #define L(i,j,k) for(ll i=(j);i<=(k);i++) #define R(i,j,k) for(ll i=(j);i>=(k);i--) #define inf 0x3f3f3f3f3f3f3f3f #define vec vector #define pll pair<ll,ll> #define fi first #define se second #define pb push_back #define mkp make_pair #define MS(i,j,k) memset(i,j,sizeof(ll)*(k+2)) const ll N=1e5+10,M=10; const ll mod=998244353,mmod=mod-1; const double pi=acos(-1),eps=1e-8; using namespace std; ll fmul(ll a,ll b){a%=mod;b%=mod;ll res=0;while(b){if(b&1){res+=a;res%=mod;}a<<=1;if(a>=mod)a%=mod;b>>=1;}return res;} ll gcd(ll x,ll y){if(y==0) return x;return gcd(y,x%y);} ll fksm(ll a,ll b){ll r=1;if(b<0)b+=mod-1;for(a%=mod;b;b>>=1){if(b&1)r=r*a%mod;a=a*a%mod;}return r;}//a 分母; b MOD-2 ll lowbit(ll x){return x&(-x);}ll m,n,t,x,y,z,l,r,u,v,k,p,pp,nx,ny,nz,ansx,ansy,num,sum,mn,mx,ans; ll lim,pos,tot,cnt,root,key,block; ll a[N],dp[N];ll fac[N],fra[N],two=fksm(2,mod-2); void init(ll n){//n階階乘初始化 fac[0]=1;L(i,1,n)fac[i]=fac[i-1]*i%mod;fra[n]=fksm(fac[n],mod-2);R(i,n-1,0)fra[i]=fra[i+1]*(i+1)%mod; } ll C(ll n,ll k){if(!n&&!k)return 1;if(n<k||k<0)return 0;return fac[n]*fra[k]%mod*fra[n-k]%mod;}//組合數(shù)ll R[N],a0[N],a1[N]; void init_ntt(ll limit){lim=1;ll k=0;while(lim<limit)lim*=2,k++;L(i,0,lim-1)R[i]=(R[i>>1]>>1)|((i&1)<<(k-1));} void ntt(ll *f,ll type){ll G=3,Gi=fksm(G,mod-2);//mod=998244353,G=3;mod=1e9+7,G=5;L(i,0,lim-1)if(i<R[i])swap(f[i],f[R[i]]);for(ll mid=1;mid<lim;mid<<=1){ll Wn=fksm(type==1?G:Gi,(mod-1)/(mid<<1));for(ll j=0;j<lim;j+=(mid<<1)){ll w=1;for(ll k=0;k<mid;k++,w=(w*Wn)%mod){ll x=f[j+k],y=w*f[j+k+mid]%mod;f[j+k]=(x+y)%mod,f[j+k+mid]=(x-y+mod)%mod;}}} }void NTT(ll *f,ll *g,ll siz0,ll siz1){init_ntt(siz0+siz1-1);L(i,siz0,lim)f[i]=0;L(i,siz1,lim)g[i]=0;ntt(f,1);ntt(g,1);L(i,0,lim-1)f[i]=(f[i]*g[i])%mod;ntt(f,-1);ll inv=fksm(lim,mod-2);L(i,0,lim-1)f[i]=f[i]*inv%mod; }void solve(){scanf("%lld%lld%lld",&n,&k,&m);MS(dp,0,k);L(i,1,n)scanf("%lld",&a[i]);L(i,1,n){L(j,0,k){a0[j]=dp[j]*fra[j]%mod;a1[j]=fksm(a[i],j)*fra[j]%mod;}NTT(a0,a1,k+1,k+1);L(j,0,k)dp[j]=(dp[j]+fksm(a[i],j)*m%mod+a0[j]*m%mod*fac[j]%mod)%mod;}printf("%lld\n",dp[k]); }int main(){// ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);// cout<<fixed<<setprecision(12);//精度init(10010);ll T=1;scanf("%lld",&T);while(T--)solve(); }

總結

以上是生活随笔為你收集整理的【2022 CCPC 华为云计算挑战赛】1005 带权子集和 (NTT 优化dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。