• 20联赛集训day7 题解


    题目太水了,是手速场。

    A

    如果 (a,b,c,d,e,f > 0),那么就是判断转换效率是否 (>1),也就是 (frac{bdf}{ace}>1 Rightarrow bdf > ace)

    但是会有 (0) 的情况,我们发现我们需要特判 (c=0,d eq 0)(a=0,b,d eq 0) 的情况,剩下的情况都能用上式判断。

    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #define U unsigned
    #define P std::pair<int,int>
    #define LL long long
    #define pb push_back
    #define MP std::make_pair
    #define all(x) x.begin(),x.end()
    #define CLR(i,a) memset(i,a,sizeof(i))
    #define FOR(i,a,b) for(int i = a;i <= b;++i)
    #define ROF(i,a,b) for(int i = a;i >= b;--i)
    #define DEBUG(x) std::cerr << #x << '=' << x << std::endl
    
    int main(){
    	// freopen("A.in","r",stdin);
        // freopen("A.out","w",stdout);
    	int T;scanf("%d",&T);
    	while(T--){
    		LL a,b,c,d,e,f;scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&e,&f);
    		// *b*d*f > e*c*a
    		if(c == 0 && d != 0){
    			puts("MEI");
    			continue;
    		}
    		if(a == 0 && b != 0 && d != 0){
    			puts("MEI");
    			continue;
    		}
    		puts(b*d*f > e*c*a ? "MEI":"FON");
    	}
    	return 0;
    }
    

    B

    考虑倒着做求出每个操作被执行了多少次,一个操作 (2) 相当于将区间内的操作次数都加上这个操作的操作次数,由于操作和询问都是单调向前的,所以可以用差分解决。

    然后操作 (1) 也可以用差分解决。

    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #define U unsigned
    #define P std::pair<int,int>
    #define LL long long
    #define pb push_back
    #define MP std::make_pair
    #define all(x) x.begin(),x.end()
    #define CLR(i,a) memset(i,a,sizeof(i))
    #define FOR(i,a,b) for(int i = a;i <= b;++i)
    #define ROF(i,a,b) for(int i = a;i >= b;--i)
    #define DEBUG(x) std::cerr << #x << '=' << x << std::endl
    
    const int MAXN = 2e5 + 5;
    const int ha = 1e9 + 7;
    
    inline void add(int &x,int y){
    	x += y;if(x >= ha)x -= ha;
    }
    int n,q;
    
    int opt[MAXN],l[MAXN],r[MAXN];
    int cf[MAXN],ans[MAXN];
    
    int main(){
    	scanf("%d%d",&n,&q);
    	FOR(i,1,q) scanf("%d%d%d",opt+i,l+i,r+i);
    	int now = 1;
    	ROF(i,q,1){
    		add(now,cf[i]);
    		// DEBUG(now);
    		if(opt[i] == 1){
    			add(ans[l[i]],now);
    			add(ans[r[i]+1],ha-now);
    		}
    		else{
    			add(cf[l[i]-1],ha-now);
    			add(cf[r[i]],now);
    		}
    	}
    	FOR(i,1,n) add(ans[i],ans[i-1]);
    	FOR(i,1,n) printf("%d%c",ans[i]," 
    "[i==n]);
    	return 0;
    }
    

    C

    考虑斯特林公式:

    [egin{aligned} sum_{S subseteq V} f(S)^k = sum_{i=0}^k left{^k_i ight} f(S)^{underline k} end{aligned} ]

    所以相当于要对于 (k=1ldots 3),计算出从所有图中有序选出 (k) 条边的方案数。

    我们枚举这个边的 (k) 元组,相当于要计算有多少个图包含它,设这个组总共有 (x) 个端点,那么方案数就是 (2^{n-x})。所以我们相当于要对所有可能的点数都计数。

    发现 (k=1) 时,答案就是 (m2^{n-1})

    发现 (k=2) 时,情况只有一条长度为 (2) 的链(长度表示边数)和两个端点不交的边,点数分别是 (3,4)。链可以通过枚举中心点解决,剩下那种情况可以容斥。

    发现 (k=3) 是,情况有五种:

    分别计算即可。

    具体说一下我是咋算的:首先情况 (5) 就是三元环计数,将边重定向为度数小的点向度数大的点连边,如果度数相同就按照编号连边,然后对于每个点,暴力遍历能到达的点打标记,再暴力遍历能到达的点的相邻的点,有标记答案就加一,复杂度是 (O(msqrt m)) 的。

    然后情况 (4) 我们考虑枚举与端点距离为 (1) 的点,然后先算出来以这个为中心的长度为 (2) 的链有多少个,对于每种可能我们都随便选某个端点的相邻的边作为另一条边,设点的度数为 (deg_v),那么答案就是

    [sum_{x=1}^m sum_{y=x+1}^m (deg_x+deg_y-2) = sum_{x=1}^m (deg_v-1)(deg_x-1) ]

    就可以 (O(m)) 的去算了,但是会多算情况 (5),对于每一个三元环都会被算 (6) 遍,减去后发现每条链都会被算 (2) 遍。

    情况 (1) 就是 (sum_i inom {deg_i}{3})

    情况 (3) 可以先枚举长度为 (2) 的链的中心,然后要求第三条边不能和中心相连,发现这样可能多算了 (3) 遍三元环,和 (2) 遍长度为 (3) 的链,减掉就行。

    补集转化就可以算出情况 (2),对应加起来就行。

    注意这里斯特林公式不能直接加上 (k=2) 的答案。。需要加恰好选两条不同边的方案。。

    #pragma GCC optimize("Ofast")
    #include <bits/stdc++.h>
    
    #define fi first
    #define se second
    #define db double
    #define U unsigned
    #define P std::pair<int,int>
    #define LL long long
    #define pb push_back
    #define MP std::make_pair
    #define all(x) x.begin(),x.end()
    #define CLR(i,a) memset(i,a,sizeof(i))
    #define FOR(i,a,b) for(int i = a;i <= b;++i)
    #define ROF(i,a,b) for(int i = a;i >= b;--i)
    #define DEBUG(x) std::cerr << #x << '=' << x << std::endl
    
    const int MAXN = 1e5 + 5;
    const int ha = 1e9 + 7;
    const int inv2 = 500000004;
    
    inline char nc(){
        #define SIZE 1000000+3
        static char buf[SIZE],*p1 = buf+SIZE,*p2 = buf+SIZE;
        if(p1 == p2){
            p1 = buf;p2 = buf+fread(buf,1,SIZE,stdin);
            if(p1 == p2) return -1;
        }
        return *p1++;
        #undef SIZE
    }
    
    template <typename T>
    inline void read(T &x){
        x = 0;int flag = 0;char ch = nc();
        while(!isdigit(ch)){
            if(ch == '-') flag = 1;
            ch = nc();
        }
        while(isdigit(ch)){
            x = (x<<1) + (x<<3) + (ch^'0');
            ch = nc();
        }
        if(flag) x = -x;
    }
    
    struct Edge{
    	int u,v;
    	Edge(int u=0,int v=0) : u(u),v(v) {}
    }e[MAXN];
    int n,m,k;
    int fac[MAXN],inv[MAXN],pw[MAXN];
    
    inline int qpow(int a,int n=ha-2){
    	int res = 1;
    	while(n){
    		if(n & 1) res = 1ll*res*a%ha;
    		a = 1ll*a*a%ha;
    		n >>= 1;
    	}
    	return res;
    }
    
    inline void prework(){
    	fac[0] = 1;FOR(i,1,MAXN-1) fac[i] = 1ll*fac[i-1]*i%ha;
    	inv[MAXN-1] = qpow(fac[MAXN-1]);ROF(i,MAXN-2,0) inv[i] = 1ll*inv[i+1]*(i+1)%ha;
    	pw[0] = 1;FOR(i,1,MAXN-1) pw[i] = 2ll*pw[i-1]%ha;
    }
    
    inline int C(int n,int m){
    	if(n < 0 || m < 0 || n < m) return 0;
    	return 1ll*fac[n]*inv[m]%ha*inv[n-m]%ha;
    }
    
    inline void add(int &x,int y){
    	x += y;if(x >= ha) x -= ha;
    }
    
    namespace BF{
    	int cnt[MAXN],now;
    
    	inline bool check(){
    		return n <= 300 && m <= 300;
    	}
    
    	inline void ins(int x){
    		if(!cnt[x]) now++;
    		++cnt[x];
    	}
    
    	inline void del(int x){
    		if(cnt[x] == 1) now--;
    		--cnt[x];
    	}
    
    	int ans,cc = 0;
    	int vis[MAXN];
    
    	inline void dfs(int step,int fg=0){
    		if(step == k+1){
    			add(ans,pw[n-now]);
    			return;
    		}
    		FOR(i,1,m){
    			ins(e[i].u);ins(e[i].v);
    			vis[i]++;
    			dfs(step+1,fg+(vis[i]==1));
    			vis[i]--;
    			del(e[i].u);del(e[i].v);
    		}
    	}
    
    	inline void Solve(){
    		dfs(1);
    		printf("%d
    ",ans);
    		// DEBUG(cc);
    		exit(0);
    	}
    }
    
    namespace Subtask1{
    	inline bool check(){
    		return k == 1;
    	}
    
    	inline int Solve(){
    		return 1ll*m*pw[n-2]%ha;
    	}
    }
    
    int deg[MAXN];
    
    namespace Subtask2{
    	inline bool check(){
    		return k == 2;
    	}
    
    	inline int Solve(){
    		int gx1 = 0;
    		FOR(i,1,m) add(gx1,m-deg[e[i].u]-deg[e[i].v]+1);
    		int gx2 = 1ll*m*(m-1)%ha;
    		add(gx2,ha-gx1);
    		int ans = 0;
    		add(ans,1ll*gx1*pw[n-4]%ha);
    		add(ans,1ll*gx2*pw[n-3]%ha);
    		add(ans,1ll*m*pw[n-2]%ha);
    		return ans;
    	}
    }
    
    namespace Subtask3{
    	inline bool check(){
    		return k == 3;
    	}
    
    	std::vector<int> G[MAXN];
    	int gx0,gx1,gx2,gx3,gx4;
    	bool vis[MAXN];
    
    	inline int gao(){
    		int res = 0;
    		FOR(u,1,n){
    			for(auto v:G[u]) vis[v] = 1;
    			for(auto v:G[u]) for(auto w:G[v]) if(vis[w]) res++;
    			for(auto v:G[u]) vis[v] = 0;
    		}
    		return res;
    	}
    
    	inline int Solve(){
    		FOR(i,1,m){
    			if(e[i].u > e[i].v) std::swap(e[i].u,e[i].v);
    			if(deg[e[i].u] <= deg[e[i].v]) G[e[i].u].pb(e[i].v);
    			else G[e[i].v].pb(e[i].u);
    		}
    		gx0 = gx1 = gx2 = gx3 = gx4 = 0;
    		FOR(i,1,n) add(gx0,C(deg[i],3));
    		gx4 = gao();
    		FOR(i,1,n) G[i].clear();
    		FOR(i,1,m) G[e[i].u].pb(e[i].v),G[e[i].v].pb(e[i].u);
    		FOR(v,1,n){
    			int s = 0;
    			for(auto x:G[v]) add(s,deg[x]-1);
    			s = 1ll*s*(deg[v]-1)%ha;
    			add(gx3,s);
    		}
    		add(gx3,ha-6ll*gx4%ha);
    		gx3 = 1ll*gx3*inv2%ha;
    		FOR(v,1,n){
    			int s = 1ll*C(deg[v],2)*(m-deg[v])%ha;
    			add(gx2,s);
    		}
    		add(gx2,ha-3ll*gx4%ha);
    		add(gx2,ha-2ll*gx3%ha);
    		gx1 = C(m,3);
    		add(gx1,ha-gx0);
    		add(gx1,ha-gx2);
    		add(gx1,ha-gx3);
    		add(gx1,ha-gx4);
    		int ans = 0;
    		if(gx0) add(ans,1ll*gx0*pw[n-4]%ha);
    		if(gx1) add(ans,1ll*gx1*pw[n-6]%ha);
    		if(gx2) add(ans,1ll*gx2*pw[n-5]%ha);
    		if(gx3) add(ans,1ll*gx3*pw[n-4]%ha);
    		if(gx4) add(ans,1ll*gx4*pw[n-3]%ha);
    		ans = 1ll*ans*fac[3]%ha;
    		add(ans,3ll*Subtask2::Solve()%ha);
    		add(ans,ha-2ll*Subtask1::Solve()%ha);
    		return ans;
    	}
    }
    
    std::mt19937 g(time(NULL));
    std::map<P,int> S; 
    
    int main(){
    	prework();
    	read(n);read(m);read(k);
    	// FOR(i,1,m) ++deg[e[i].u],++deg[e[i].v]; 
    	FOR(i,1,m) read(e[i].u),read(e[i].v),++deg[e[i].u],++deg[e[i].v];
    	if(BF::check()) BF::Solve();
    	else if(Subtask1::check()) printf("%d
    ",Subtask1::Solve());
    	else if(Subtask2::check()) printf("%d
    ",Subtask2::Solve());
    	else if(Subtask3::check()) printf("%d
    ",Subtask3::Solve());
    	return 0;
    }
    
  • 相关阅读:
    深入方法(22)- 指针参数
    深入方法(21)- 开放数组参数
    深入方法(20)- 静态数组参数
    深入方法(19)- 过程中的方法
    深入方法(18)- 在接口区声明的方法都相当于提前声明了
    深入方法(17)- 提前声明
    WNMP(Windows + Nginx + PHP + MySQL) 安装
    Yii2框架 数据库常用操作
    Python 生成器与迭代器 yield 案例分析
    Python VS PHP 基础语法
  • 原文地址:https://www.cnblogs.com/rainair/p/14305140.html
Copyright © 2020-2023  润新知