• 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;
    }
    
  • 相关阅读:
    CF1539 VP 记录
    CF1529 VP 记录
    CF875C National Property 题解
    CF1545 比赛记录
    CF 1550 比赛记录
    CF1539E Game with Cards 题解
    CF1202F You Are Given Some Letters... 题解
    vmware Linux虚拟机挂载共享文件夹
    利用SOLR搭建企业搜索平台 之九(solr的查询语法)
    利用SOLR搭建企业搜索平台 之四(MultiCore)
  • 原文地址:https://www.cnblogs.com/rainair/p/14305140.html
Copyright © 2020-2023  润新知