zoukankan      html  css  js  c++  java
  • 联考20200618 T1 墨水大师

    题目:

    分析:
    考虑树的情况,把根的颜色确定之后剩下的颜色只需要与父亲不同就好了,答案为(C(C-1)^{n-1})
    考虑环的情况,答案需要减去终点和起点颜色相同的情况,强行合并起点终点答案为(C(C-1)^{n-1}),但是发现这样多减了终点和倒数第二个点相同的情况。。。
    考虑容斥
    假设一个环的长度为(n),答案为(sum_{i=1}^{n}(-1)^{i-1}C(C-1)^{n-i})
    发现这是一个等比数列,当我们知道C之后就可以求出任意环大小的答案
    运用一个有趣的性质
    一个(n)个点的仙人掌最多由(sqrt{n})种大小的环组合起来
    于是预处理仙人掌的环,然后对于每一个(C)暴力计算即可

    复杂度(O(qsqrt{n}logMOD))(log)是求逆元
    这玩意还被卡我无话可说,不优化了(2333

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    
    #define maxn 400005
    #define MOD 998244353
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m,q;
    int fir[maxn],nxt[maxn],to[maxn],cnt;
    int dfn[maxn],low[maxn],tim,stk[maxn],tp;
    int b[maxn];
    int Sz[maxn],Tim[maxn],cur;
    
    inline void newnode(int u,int v)
    {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    
    inline void tarjan(int u)
    {
    	dfn[u]=low[u]=++tim,stk[++tp]=u;
    	for(int i=fir[u];i;i=nxt[i])
    		if(!dfn[to[i]])
    		{
    			tarjan(to[i]),low[u]=min(low[u],low[to[i]]);
    			if(low[to[i]]>=dfn[u])
    			{
    				int num=0,x;
    				do{x=stk[tp--],num++;}while(x!=to[i]);
    				b[num]++;
    			}
    		}
    		else low[u]=min(low[u],dfn[to[i]]);
    }
    
    inline int ksm(int num,int k)
    {
    	int ret=1;
    	for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
    	return ret;
    }
    inline int calc(int N,int C)
    {
    	int P=MOD-ksm(C-1,MOD-2),A=ksm(C-1,N);
    	P=1ll*(1-ksm(P,N))*ksm(1-P,MOD-2)%MOD;
    	return 1ll*A*P%MOD;
    }
    
    int main()
    {
    	n=getint(),m=getint(),q=getint();
    	for(int i=1;i<=m;i++)
    	{
    		int u=getint(),v=getint();
    		newnode(u,v),newnode(v,u);
    	}
    	tarjan(1);
    	for(int i=1;i<=n;i++)if(b[i])Sz[++cur]=i,Tim[cur]=b[i];
    	while(q--)
    	{
    		int C=getint();
    		int tmp=1;
    		for(int i=1;i<=cur;i++)
    			tmp=1ll*tmp*ksm(calc(Sz[i],C),Tim[i])%MOD;
    		printf("%lld
    ",1ll*C*tmp%MOD);
    	}
    }
    

  • 相关阅读:
    取一定范围的随机数
    小菜学Chromium之OpenGL学习之二
    程序员健康之路
    解密硬件解码关键技术
    Android 图片开发内幕系列第一篇
    你所不知道的html5与html中的那些事第三篇
    如何加密android apk
    linux设备驱动第五篇:驱动中的并发与竟态
    快速调试chromium
    小菜鸟带着梦想学chromium
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13160092.html
Copyright © 2011-2022 走看看