• 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;
    }
    

      

  • 相关阅读:
    [leetCode]Reverse Words in a String
    [leetCode]Word Break
    [leetCode]Unique Binary Search Trees
    [leetCode]Binary Tree Inorder Traversal 递归 && 栈解法
    [leetCode]Binary Tree Zigzag Level Order Traversal
    [leetCode]Binary Tree Level Order Traversal
    [leetCode]Binary Tree Maximum Path Sum
    freemarker生成静态页面中文乱码(固定中文和动态生成的中文都乱码)
    多线程-安全的终止线程
    多线程-理解中断
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/5860593.html
Copyright © 2020-2023  润新知