Codeforces Round 1007 (Div. 2)


A. The Play Never Ends

题意:三个人比赛,每场两个人比赛,另一个人在观众席,观众席替换输的人,但如果有一个人以及连续上场两次,就得下场,让其它两个人比。求第一场比赛在观众席的人在第k场是不是也能在观众席。

找规律,模拟一下发现第二三场不得不上台,然后第四场下台,就这样一直循环。于是看取余3是不是1。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    if (n % 3 == 1) {
    	std::cout << "YES\n";
    } else {
    	std::cout << "NO\n";
    }
}

B. Perfecto

题意:构造一个排列,使得没有一个前缀的和是平方数。

先按1到n的顺序排好,然后从前往后看,如果当前位置的前缀和是平方数,就和后面的数换,这样前缀和会加一,就不是平方数。要特判i=1ni是平方数的情况。

点击查看代码
void solve() {
    i64 n;
    std::cin >> n;
    i64 sum = n * (n + 1) / 2;
    i64 t = std::sqrt(sum);
    if (t * t == sum) {
    	std::cout << -1 << "\n";
    	return;
    }

    if (n == 2) {
    	std::cout << 2 << " " << 1 << "\n";
    	return;
    }

    std::vector<int> ans(n);
    std::iota(ans.begin(), ans.end(), 1);

    i64 pre = 0;
    for (int i = 0; i < n; ++ i) {
    	pre += ans[i];
    	i64 t = std::sqrt(pre);
	    if (t * t == pre) {
	    	pre -= ans[i];
	    	std::swap(ans[i], ans[i + 1]);
	    	pre += ans[i];
	    }
    }

    for (int i = 0; i < n; ++ i) {
    	std::cout << ans[i] << " \n"[i == n - 1];
    }
}

C. Trapmigiano Reggiano

题意:给你一棵树,有一个老鼠从st要到en,你可以每次指出一个点,老鼠就会往这个点的方向移动一条边。给出一个操作的排列,使得最后老鼠在en

这题也靠猜。
刚开始一直想以st为根这么拉扯可以到en,后来发现以en为根,直接后序遍历输出就行。因为这样相当于从每个叶子开始往en操作,这样如果老鼠一定会往en靠近。

点击查看代码
void solve() {
    int n, st, en;
    std::cin >> n >> st >> en;
    -- st, -- en;
    std::vector<std::vector<int>> adj(n);
    for (int i = 1; i < n; ++ i) {
    	int u, v;
    	std::cin >> u >> v;
    	-- u, -- v;
    	adj[u].push_back(v);
    	adj[v].push_back(u);
    }

    std::vector<int> ans;
    auto dfs = [&](auto self, int u, int fa) -> void {
    	for (auto & v : adj[u]) {
    		if (v == fa) {
    			continue;
    		}

    		self(self, v, u);
    	}
    	ans.push_back(u);
    };

    dfs(dfs, en, -1);
    for (auto & x : ans) {
    	std::cout << x + 1 << " \n"[x == ans.back()];
    }
}

D1. Infinite Sequence (Easy Version)

题意:给出a的前n项,规定m>n,am=i=1m2ai,求am

赛时已经想出n为奇数怎么做了,但因为已经写红温了,没想到n是偶数直接加一变成偶数就行了。
这里设n为偶数,如果不是我们就给他加一,然后预处理出12na以及前缀异或和sum。我们发现对于一个m2m2=2m+12,这意味着a中大于n的项相邻两项是相同的,那么我们只需要看m奇偶性,如果是偶数则最后一项不能和前面消掉,就需要求am2,否则都消掉了,只剩下a的前n项异或和,这个我们已经求出来了。于是递归求解即可。

点击查看代码
void solve() {
    i64 n, l, r;
    std::cin >> n >> l >> r;
    std::vector<int> a(3 * n + 1), sum(3 * n + 1);
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    	sum[i] = sum[i - 1] ^ a[i];
    }

    for (int i = n + 1; i <= 3 * n; ++ i) {
    	a[i] = sum[i / 2];
    	sum[i] = sum[i - 1] ^ a[i];
    }
    
    if (n % 2 == 0) {
    	++ n;
    }

    if (l <= 2 * n) {
    	std::cout << a[l] << "\n";
    	return;
    }

    auto get = [&](auto self, i64 m) -> i64 {
    	if (m <= 2 * n) {
    		return a[m];
    	}
    	
    	if (m & 1) {
    		-- m;
    	} 

    	m /= 2;

    	if (m & 1) {
    		return sum[n];
    	}

    	return sum[n] ^ self(self, m);
    };

    std::cout << get(get, l) << "\n";
}
posted @   maburb  阅读(196)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示