定义: f n ( x ) = f ( f n − 1 ( x ) ) f_n(x)=f(f_{n-1}(x)) fn(x)=f(fn−1(x)),给定 f 1 ( x ) f_1(x) f1(x),现定义一函数 g ( x ) , g ( x ) = lim n → ∞ 1 n ∑ i = 1 n f i ( x ) g(x),g(x)=\lim_{n \to \infty} {1 \over n}\sum_{i=1}^{n}{f_i(x)} g(x),g(x)=limn→∞n1∑i=1nfi(x),问是否对于所有的 x x x,都有 x = g ( x ) x=g(x) x=g(x)
易知(反证)至少存在一个这样的集合,集合内的元素满足 f n ( x ) = y , f n − 1 ( y ) = z , f n − 2 ( z ) = x f_n(x)=y,f_{n-1}(y)=z,f_{n-2}(z)=x fn(x)=y,fn−1(y)=z,fn−2(z)=x这样的内部循环,而不再这种集合内的元素,也可以通过多次 f n ( x ) = f ( f n − 1 ( x ) ) f_n(x)=f(f_{n-1}(x)) fn(x)=f(fn−1(x))关系与这些集合中的一个元素产生联系,当产生联系后, f n ( x ) = f ( f n − 1 ( x ) ) f_n(x)=f(f_{n-1}(x)) fn(x)=f(fn−1(x))使得它的值在这个集合中循环,所以当 n → ∞ n \to \infty n→∞时, g ( x ) , g ( x ) = lim n → ∞ 1 n ∑ i = 1 n f i ( x ) = ∑ 对 应 集 合 的 所 有 元 素 之 和 对 应 集 合 的 元 素 个 数 g(x),g(x)=\lim_{n \to \infty} {1 \over n}\sum_{i=1}^{n}{f_i(x)}={\sum对应集合的所有元素之和 \over 对应集合的元素个数} g(x),g(x)=limn→∞n1∑i=1nfi(x)=对应集合的元素个数∑对应集合的所有元素之和,所以如果满足所有 x = g ( x ) x=g(x) x=g(x),则所有集合的平均值相等
ps:注意精度问题, a b = c d ⇒ a ∗ d = b ∗ c {a \over b}={c \over d} \Rightarrow a*d = b*c ba=dc⇒a∗d=b∗c,采用乘法比较
AcCode:
//#pragma GCC optimize(2)
//#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <fstream>
#include <cmath>
#define pint std::pair<int,int>
#define in std::cin
#define out std::cout
#define SYNC std::ios::sync_with_stdio(false);
const int N = 2e5 + 10;
std::vector<pint> ans;
int cnt[N];
int edge[N];
inline void getAns(int rt, int sum, int num, int p) {
if (rt == p) ans.push_back(std::make_pair(sum, num));
else getAns(edge[rt], sum + edge[rt], num + 1, p);
}
inline void dfs(int rt, int rem) {
cnt[rt] = rem;
if (cnt[edge[rt]] == rem) getAns(edge[rt], edge[rt], 1, rt);
else if (cnt[edge[rt]] == 0) dfs(edge[rt], rem);
}
signed main() {
SYNC;
//std::ifstream in("input.txt");
//std::ofstream out("out.txt", std::ios::out);
//if (!in.is_open()) {
// std::cout << "error!" << std::endl;
// return 0;
//}
int t; in >> t;
while (t--) {
ans.clear();
int n, rem = 0; in >> n;
for (int i = 1; i <= n; i++) cnt[i] = 0;
for (int u = 1; u <= n; u++) { in >> edge[u]; if (u == edge[u]) rem++; }
if (rem > 1) { out << "NO\n"; continue; }
for (int i = 1, num = 1; i <= n; i++) if (!cnt[i]) dfs(i, num++);
bool flag = true;
for (int i = 0; i < ans.size() - 1; i++) if (ans[i].first * ans[i + 1].second != ans[i].second * ans[i + 1].first) { flag = false; break; }
if (flag) out << "YES\n";
else out << "NO\n";
}
//if (in.eof()) std::cout << "OK!\n";
//in.close();
//out.close();
}


被折叠的 条评论
为什么被折叠?



