zoukankan      html  css  js  c++  java
  • 【THUWC2019模拟2019.1.18】Counting

    Description

    羽月最近发现,她发动能力的过程是这样的:
    构建一个 V (V<=100)个点的有向图 G,初始为没有任何边,接下来羽月在脑中构建出一个长度为 E 的边的序列,序列中元素两两不同,然后羽月将这些边依次加入图中,每次加入之后计算当前图的强连通分量个数并记下来,最后得到一个长度为E 的序列,这个序列就是能力的效果。
    注意到,可能存在边的序列不同而能力效果相同的情况,所以羽月想请你帮她计算能发动的不同能力个数,答案对 998244353 取模。你需要对于1<=E<=V*(V-1)的所有 E 计算答案。

    Solution

    • 一道题意使我懵逼的题目
    • 既然我们要求的是强联通分量序列不同的个数,我们不妨设f[i]表示连了i条边的个数。然后我们枚举又合并了多少个强联通分量。
    • 显然i条边是不足以表示这个状态的。
    • 考虑与强联通分量有关的几个量:点数,链数…
    • 注意到有一种可以构造最少强联通分量的贪心的连法,从一个强联通分量中分出一条链,然后再用一条边把这个链变成强联通分量。
    • 一团强联通分量伸出一条链,没有别的边,这可以使我们用最少的边构造出最多种可能的连法(雾),从而使得计数不会缺漏。
    • 根据以上的思路,设状态f[i][j][k]表示i条边,j+k个点在当前的联通块内,伸出一条长度为k的链,不同强连通分量序列的个数(也就是阶段性的答案)。
    • 如果j+k<n,新的一条边要么从链连到一个不在联通块内的点f[i][j][k]->f[i+1][j][k+1]
      ,要么将l个链上的点合并带强联通分量中f[i][j][k]->f[i+1][j+l][k+l].
    • 否则如果k>0我们还可以把这些点合并。
    • 但要是k=0的话,我们就不能再贪心地连边了,接下来连的边就是对答案无关紧要的了。换句话说,就是不管连什么都不会改变强联通分量的个数。f[i][j][k]->f[i+1][j][k]
    • 在转移过程中,应该保证边数在一个范围内。即i<=j*(j-1)+k*(k-1)/2+j*k。保证定义的状态的性质。
    • 这题对于我来说还是十分有思维难度的。。。。。。
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define maxn 105
    #define ll long long 
    #define mo 998244353
    using namespace std;
    
    int n,i,j,k,l,p,q;
    ll f[2][maxn][maxn],ans;
    
    int main(){
    	freopen("counting.in","r",stdin);
    	freopen("counting.out","w",stdout);
    	scanf("%d",&n);
    	f[0][1][0]=1;
    	for(i=0;i<(n-1)*n;i++){
    		if (i==6){
    			printf("");
    		}
    		p=i&1,q=p^1;
    		memset(f[q],0,sizeof(f[q]));
    		ans=0;
    		for(j=0;j<=n;j++) for(k=0;k<=n-j;k++) if (f[p][j][k]){
    			for(l=1;l<=k;l++) 
    				(f[q][j+l][k-l]+=f[p][j][k])%=mo;
    			if (j+k<n) (f[q][j][k+1]+=f[p][j][k])%=mo;
    			else if (i+1<=j*(j-1)+k*(k-1)/2+j*k)
    				(f[q][j][k]+=f[p][j][k])%=mo;
    		}
    		for(j=0;j<=n;j++) for(k=0;k<=n-j;k++) 
    			(ans+=f[q][j][k])%=mo;
    		printf("%lld ",ans);
    	}
    }
    
    
  • 相关阅读:
    自制操作系统Antz(11)——实现shell(下)命令响应
    自制操作系统Antz(10)——实现shell(上)
    利用Android-FingerprintManager类实现指纹识别
    C语言解析WAV音频文件
    自制病毒——控制桌面鼠标以及开关机
    Linux内核源码分析 day01——内存寻址
    后端必备的Linux知识
    Java基础面试题总结
    自制操作系统Antz(9)——实现内核 (下) 实现图形化界面
    自制操作系统Antz(8)——实现内核 (中) 扩展内核
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700956.html
Copyright © 2011-2022 走看看