zoukankan      html  css  js  c++  java
  • CF # 369 D2 D、E

    D,只要抓住每个点只有一个出度,那么图就能分成几个部分,而且可以发现,一个部分最多一个环。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    #define LL long long
    const int MAXN = 200005;
    const int MOD = 1e9 + 7;
    int nt[MAXN];
    
    int two[MAXN];
    int part[MAXN];
    int visit[MAXN];
    int acyc[MAXN], acyn[MAXN];
    
    int n, cyc, cyn;
    
    void dfs2(int u){
    	visit[u] = 3;
    	acyc[cyc] ++;
    	if(visit[nt[u]] == 3) return ;
    	dfs2(nt[u]);
    }
    
    
    void dfs(int u){
    	
    	visit[u] = 2;
    	if(visit[nt[u]] == 0){
    		dfs(nt[u]);
    	}
    	else if(visit[nt[u]] == 1){
    		cyn = part[nt[u]];
    	//	visit[nt[u]] = 1;
    	}
    	else{
    		cyc ++;
    		cyn = cyc;
    		dfs2(nt[u]);
    	}
    	visit[u] = 1;
    	part[u] = cyn;
    	acyn[cyn]++;
    }
    
    int main(){
    	
    	
    	two[0] = 1;
    	for(int i =1 ; i < MAXN; i++)
    		two[i] = (two[i - 1] * 2) % MOD;
    	
    	
    	scanf("%d", &n);
    	memset(visit, 0, sizeof(visit));
    	memset(part, -1, sizeof(part));
    	for(int i = 1; i <= n; i++)
    		scanf("%d", &nt[i]);
    	
    	cyc = cyn = 0;
    	
    	for(int i = 1; i <= n; i++){
    		if(visit[i] == 0){
    			cyn = 0;
    			dfs(i);
    		}
    	}
    	
    	int ans = 1;
    	/*
    	for(int i = 1; i <= n; i++)
    		printf("%d  ", part[i]);
    	puts("");
    	
    	for(int i = 0; i <= cyc; i++){
    		printf("%d %d 
    ", acyc[i], acyn[i]);
    	}*/
    	
    	for(int i = 0; i <= cyc; i++){
    		if(i == 0 && acyn[i] > 0){
    			ans = ((LL)ans * two[acyn[i] - 1])%MOD;
    		}
    		if(i > 0){
    			ans = (LL)ans * (two[acyn[i]] - (LL)2 * two[acyn[i] - acyc[i]]) % MOD;
    		}
    	}
    	if(ans < 0) ans = ((LL)ans + MOD) % MOD;
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    

      

    E,题解在注释

    /*****************
    
    设 2^n = m ,分母为 m ^k ,算的分子为 m * (m - 1) *.... * (m - k + 1)
    只要两个互质,最后用1减就是了,至于化简的过程,就是对分子提取因子2.
    
    边界 太多,搞了一晚……不划算
    
    
    
    ***********/
    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    
    using namespace std;
    #define LL long long
    
    const int MOD =1000003;
    
    int mod[MOD + 5];
    bool vis[MOD + 5];
    
    LL tail[100];
    
    
    int quick(int m, LL k){
    	int ret = 1;
    	int pow = m;
    	while(k){
    		if(k&1)
    		ret = (LL)ret * pow % MOD;
    		k >>= 1;
    		pow = (LL)pow * pow % MOD;
    	}
    	return ret;
    }
    
    
    int cal(LL n, int index){
    	
    	int m = quick(2, n);
    	int ret = 1;
    	int counts = 0;
    	
    	memset(vis, false, sizeof(vis));
    	
    	for(LL i = 1; i <= tail[index]; i += 2){
    		if(vis[(((LL)m - i)%MOD + MOD)%MOD]){
    			break;
    		}
    		mod[counts++] = (((LL)m - i)%MOD + MOD) %MOD;
    		vis[mod[counts - 1]] = true;
    	}
    	
    //	cout << counts << endl;
    	
    	LL mc = tail[index] / 2  + 1;
    	LL cc = mc / counts;
    	
    
    	mc = mc % counts;
    	
    	for(int i = 0; i < counts; i++)
    		ret = ((LL)ret * mod[i]) % MOD;
    	
    	ret = quick(ret, cc);
    	for(int i = 0; i < mc; i++){
    		ret = ((LL)ret * mod[i]) %MOD;
    	}
    	
    //	cout <<"endl" << endl;
    	
    	return ret;
    	
    	
    	
    }
    
    int main(){
    	
    	LL n, k, tmp;
    	int counts = 0;
    	cin >> n >> k;
    	
    	double tt = log(k) / log(2) - n;
    	
    	if(n < 64){
    		if( tt > 1e-8){
    			cout << 1 << " " << 1 << endl;
    			return 0;
    		}
    		else if(tt < 1e-8){
    			
    			LL ans = 1;
    			
    			for(LL i = 1; i <= n; i++)
    				ans = ans * 2;
    			
    			if(ans > 0 && ans < k){
    				cout << 1<< " "<< 1 << endl;
    				return 0;
    			}
    			
    			
    		}
    	}
    	
    	tmp = k - 1;
    	
    	LL upc = 0;
    	
    	while(tmp){
    		
    		if(tmp % 2 == 0){
    			
    			upc += tmp / 2;
    			
    			tail[counts++] = tmp - 1;
    			tmp = tmp / 2;
    		}
    		else {
    			upc += tmp / 2;
    			tail[counts++] = tmp;
    			tmp = (tmp - 1) / 2;
    		}
    		
    	}
    	
    //	cout << upc << endl << endl;
    	
    	LL k_1 = k - 1 - upc;
    	
    	int down = quick(2, n - 1);
    	down = quick(down, k - 1);
    	down = (LL)down * quick(2, k_1) % MOD;
    	
    	
    	int up = 1;
    	
    //	cout << down <<endl;
    	
    //	cout << "YES" << counts <<endl;
    	
    	for(int i = 0; i < counts; i++){
    		up = ((LL)up * cal(n - i, i))%MOD;
    	}
    	
    	up = ((down - up) % MOD + MOD) %MOD;
    	
    	cout << up  <<" "<< down << endl;
    }
    

      

  • 相关阅读:
    golang-switch结构辨析有话
    不用中间变量交换变量值-golang版
    vue element ui表单验证不通过,滚动到页面上第一个验证失败的输入框位置
    表单校验中使用v-if和v-else来判断是福哦要校验时的注意项
    如何修改本地项目关联的远程仓库地址
    vue-cli3如何访问public文件夹下的静态资源
    Git 命令行的各种退出方式
    elementui表格如何在表头每个列标题后面插入图片用于插入tooltip
    js 把一个二叉树类型的对象转化为普通对象
    element-ui树结构设置默认选中节点时改变传入的数组树结构没有变化
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/5860593.html
Copyright © 2011-2022 走看看