zoukankan      html  css  js  c++  java
  • 【UOJ#75】【UR #6】智商锁(矩阵树定理,随机)

    【UOJ#75】【UR #6】智商锁(矩阵树定理,随机)

    题面

    UOJ

    题解

    这种题我哪里做得来啊[惊恐],,,
    题解做法:随机(1000)个点数为(12)的无向图,矩阵树定理算出它的生成树个数,然后找到四张图不拼接直接放在一起,也就是找到四个图,假设其生成树个数是(f(G)),那么就找到(f(G_1)f(G_2)f(G_3)f(G_4)equiv k),然后预处理两两的乘积,丢到哈希表/( ext{map})里,枚举另外一半直接查。。。
    无向图的生成方式是每条边出现的概率是(0.8)。然后(rand)的时候确保图连通。
    还需要再特判一下(k=0)的情况。

    然后概率的证明直接蒯题解吧。。。

    首先我们随机无向图的方法是每一条边生成的概率都是(0.8),而(12)个点的完全图的生成树个数是(12^{10}),这是远大于模数的,所以我们可以近似地把(f_i)看做均匀分布的随机数(这个和我们平时写的哈希表的思想类似)。接下来我们把这(1000)个随机数的集合四次方再模上模数,这样我们就得到了(10^{12})个数,和刚才同理,我们也可以把这(10^{12})个数给近似地看成均匀分布的随机数。

    接下来我们要求的是(10^{12})个小于等于(10^9)的随机数完全覆盖(0)(10^9)之间所有数的概率是多少。首先一个数被覆盖的概率是(1-(1-frac{1}{10^9})^{10^{12}} approx 1-mathrm{e}^{-10^3}),我们可以近似地认为所有数都被覆盖的概率是((1-mathrm{e}^{-10^3})^{10^9}),实际上这个数是非常接近(1)的(因为(e^{10^3})(10^9)大到哪里去都不知道了)

    打不过打不过。

    #include<iostream>
    #include<cstdio>
    #include<map>
    using namespace std;
    #define MOD 998244353
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
    struct Graph
    {
    	int g[15][15],a[15][15],T,edge;
    	void Calc()
    	{
    		T=1;
    		for(int i=2;i<=12;++i)
    		{
    			for(int j=i+1;j<=12;++j)
    				while(a[j][i])
    				{
    					int t=a[i][i]/a[j][i];
    					for(int k=i;k<=12;++k)a[i][k]=(a[i][k]+MOD-1ll*a[j][k]*t%MOD)%MOD;
    					for(int k=i;k<=12;++k)swap(a[i][k],a[j][k]);
    					T=MOD-T;
    				}
    		}
    		for(int i=2;i<=12;++i)T=1ll*T*a[i][i]%MOD;T=(T+MOD)%MOD;
    	}
    	void Add(int u,int v){++edge;g[u][v]=g[v][u]=1;a[u][v]--;a[v][u]--;a[u][u]++;a[v][v]++;}
    	void Rand()
    	{
    		for(int i=2;i<=12;++i)Add(rand()%(i-1)+1,i);
    		for(int i=1;i<=12;++i)
    			for(int j=i+1;j<=12;++j)
    				if(!g[i][j]&&rand()%10<8)
    					Add(i,j);
    		Calc();
    	}
    	void Output(int N)
    	{
    		for(int i=1;i<=12;++i)
    			for(int j=i+1;j<=12;++j)
    				if(g[i][j])printf("%d %d
    ",N+i,N+j);
    	}
    }G[1010];
    pair<int,int> a[1010101];
    int S[1010101],tot;
    map<int,pair<int,int> >M;
    void Output(int a,int b,int c,int d)
    {
    	printf("48 %d
    ",G[a].edge+G[b].edge+G[c].edge+G[d].edge+3);
    	G[a].Output(0);G[b].Output(12);G[c].Output(24);G[d].Output(36);
    	printf("1 13
    13 25
    25 37
    ");
    }
    int main()
    {
    	for(int i=1;i<=1000;++i)G[i].Rand();
    	for(int i=1;i<=1000;++i)
    		for(int j=i;j<=1000;++j)
    			++tot,M[S[tot]=1ll*G[i].T*G[j].T%MOD]=a[tot]=make_pair(i,j);
    	int T=read();
    	while(T--)
    	{
    		int K=read();if(!K){puts("2 0");continue;}
    		for(int i=1;i<=tot;++i)
    		{
    			int v=1ll*K*fpow(S[i],MOD-2)%MOD;
    			if(M.find(v)!=M.end())
    			{
    				Output(a[i].first,a[i].second,M[v].first,M[v].second);
    				break;
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android开发技术周报 Issue#101
    Android开发技术周报 Issue#102
    Android开发技术周报 Issue#100
    Android开发技术周报 Issue#98
    Android开发技术周报 Issue#99
    ANDROID开发技术周报 ISSUE#90
    ANDROID开发技术周报 ISSUE#91
    Android开发技术周报 Issue#0
    Android开发技术周报 Issue#2
    c#中的delegate(委托)和event(事件)
  • 原文地址:https://www.cnblogs.com/cjyyb/p/11088753.html
Copyright © 2011-2022 走看看