2019.01.19-2018年6月NEYC集训counting
生活随笔
收集整理的這篇文章主要介紹了
2019.01.19-2018年6月NEYC集训counting
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述:
羽月最近發現,她發動能力的過程是這樣的:
構建一個 V 個點的有向圖 G,初始為沒有任何邊,接下來羽月在腦中構建出一個長度為 E 的邊的序列,序列中元素兩兩不同,然后羽月將這些邊依次加入圖中,每次加入之后計算當前圖的強連通分量個數并記下來,最后得到一個長度為E 的序列,這個序列就是能力的效果。
注意到,可能存在邊的序列不同而能力效果相同的情況,所以羽月想請你幫她計算能發動的不同能力個數,答案對 998244353 取模。你需要對于1<=E<=V*(V-1)的所有 E 計算答案。
算法標簽:前綴和優化dp
思路:
考慮對于一個可行的序列,令組成方案表示成一個大的包含多個點的強連通分量,其余點都為單獨的連通分量能表示所以情況。
我們考慮一次把x個點縮進大的連通分量,需要x+1條邊。
對于已有j個點在大連通分量內時,邊至多只有j*j+(n-j)*(n-j+1)/2+j*(n-j)條。
倘若令k為縮過幾次點,則邊至少有j+k-1條。
考慮dp
令f[i][j][k]表示加到第i條邊,有j個點在大連通分量內,鎖了k次點。
式子是:
f[i][j][k]=f[i-1][j][k]+∑f[i-1][j-p][k]
于是考慮前綴和優化,記sum[j-1][k]為∑f[i-1][j-p][k]
以下代碼:
#include<bits/stdc++.h> #define il inline #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=105,p=998244353; int n,f[2][N][N],op,sum[N][N]; il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x; } il int mu(int x,int y){if(x+y>=p)return x+y-p;return x+y; } int main() {n=read();f[0][1][0]=1;for(int i=0;i<=n;i++)sum[1][0]=1;for(int i=1;i<=n*(n-1);i++){op^=1;for(int j=1;j<=n;j++)for(int k=0;k<=n;k++)f[op][j][k]=0;for(int j=1;j<=n;j++){if(j*(j-1)+(n-j)*(n-j-1)/2+j*(n-j)<i)continue;for(int k=0;k<=n;k++){if(k+j-1>i)break;if(k)f[op][j][k]=mu(f[op^1][j][k],sum[j-1][k-1]);else f[op][j][k]=f[op^1][j][k];}}int ans=0;for(int j=1;j<=n;j++){for(int k=0;k<=n;k++){sum[j][k]=mu(sum[j-1][k],f[op][j][k]);ans=mu(ans,f[op][j][k]);}}printf("%d ",ans);}puts("");return 0; } View Code?
轉載于:https://www.cnblogs.com/Jessie-/p/10291538.html
總結
以上是生活随笔為你收集整理的2019.01.19-2018年6月NEYC集训counting的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你必须拥有的Python调试神器
- 下一篇: OSPF(三)