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 \n", 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\n", 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;
}

  

时间: 2024-08-11 01:24:09

CF # 369 D2 D、E的相关文章

CF #330 D2 E

相当于给你一些点,要你最多删除不超过k,使得能使用一个边长为整数的长方形,与XY轴平行,使长方形的面积最小. 上课时拿笔来画画,然后忽然思路就开了,要是比赛也这样就好了~~先按X,Y分别排序,由于K较小,而且,删除的时候肯定会删除最外围的点,所以,可以上下左右枚举删了哪些点,排序后的数组来模拟这个过程,最多4^K个选择,可以过. #include <iostream> #include <cstdio> #include <cstring> #include <a

CF #327 DIV2 D、E

两题都不难. 对于D题,可以使用相对移动,把吹aircraft移动变成相反方向的待援点的移动.假设此时时间为t,把aircraft的速度设为Vmax,看待援点在飞船最大速度飞行t秒的范围内,注意风向变化的时间点即可.其实很明显的二分.. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7

CF#310 d2

A:|c[1]-c[0]| B:A+-(oc)A[0]==0..n-1 C: #include <cstdio> int n,m,i,j,k,p; int ll,ca,cb,cc; int main(){ scanf("%d%d",&n,&m); for(;i<m;++i){ scanf("%d",&p); scanf("%d",&ll); ++ca; if(ll==1) while(--p){

Codeforces 369 E 离线、思维

E. Valera and Queries 题意:横坐标轴上,给出 n 段区间(可交叉). 有 m 个询问,每次询问给出多个点,求这 n 段区间有多少段至少包含了一个点. tags:离线+树状数组 1]数据量太大,所以肯定离线处理. 2]给出的是区间,而询问给出的是点,我们必须想办法把询问的点转化为区间.所以对于每次给出的 k 个点,我们取出它们分割出的区间. 3]要求多少个区间包含了点,我们反过来求有多少个区间没有包含任何点.如果给出的区间在分割出来的区间内部,那么这个区间肯定就没有包含这次询

CF 1142A(性质、暴举)

队友和大佬都什么几种情况啥的……我是把终点都插了,起点随便选一个,暴举答案莽A. 1 const int maxn = 1e5 + 5; 2 ll n, k, a, b, aa, minn = INF, maxx = -1; 3 set<ll> bb; 4 5 ll gcd(ll a, ll b) { 6 return b ? gcd(b, a % b) : a; 7 } 8 9 int main() { 10 cin >> n >> k >> a >

CF 1142C(转化、凸包)

可以变换坐标:x' = x, y' = y - x ^ 2,如此之后可得线性函数x' * b + c = y',可以发现两点连边为抛物线,而其他点都在这条线下方才满足题意,故而求一个上凸壳即可. 1 #include <cstdio> 2 #include <cmath> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 using namespace std;

一场CF的台前幕后(上)——转

前奏 大约4月份的时候,业界毒瘤pyx噔噔噔跑过来说:“酷爱!我YY了一道题!准备当CF的C” 我当时就被吓傻了."Yet another Chinese round?" “区间取模,区间求和” 感觉这题还不错?不过pyx嫌水了…… 好办!当时我刚刚出完动态仙人掌不久,于是一拍脑袋说:把这个问题出到仙人掌上去! 当然被pyx鄙视了…… 后来一直就没啥动静,直到5月底的CTSC. 试机的时候pyx给我看了套他出的神题……里面有一道题……我不小心读成了下面这个样子: “给定n个m维的模2意

你会用::before、::after吗

::before和::after伪元素的用法 一.介绍 css3为了区分伪类和伪元素,伪元素采用双冒号写法. 常见伪类——:hover,:link,:active,:target,:not(),:focus. 常见伪元素——::first-letter,::first-line,::before,::after,::selection. ::before和::after下特有的content,用于在css渲染中向元素逻辑上的头部或尾部添加内容. 这些添加不会出现在DOM中,不会改变文档内容,不可

[nRF51822] 10、基础实验代码解析大全 &#183; 实验15 - RTC

一.实验内容: 配置NRF51822 的RTC0 的TICK 频率为8Hz,COMPARE0 匹配事件触发周期为3 秒,并使能了TICK 和COMPARE0 中断. TICK 中断中驱动指示灯D1 翻转状态, 即指示灯D1 以8Hz 的速率翻转状态 COMPARE0 中断中点亮指示灯D2 二.nRF51822的内部RTC结构: NRF51822 有两个RTC 时钟:RTC0,RTC1.两个RTC 均为24 位,使用LFCLK 低频时钟,并带有12 位分频器,可产生TICK.compare 和溢出