結果
| 問題 | No.3441 Sort Permutation 2 |
| コンテスト | |
| ユーザー |
npnp
|
| 提出日時 | 2026-02-06 22:36:50 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 6,860 bytes |
| 記録 | |
| コンパイル時間 | 6,422 ms |
| コンパイル使用メモリ | 387,268 KB |
| 実行使用メモリ | 18,132 KB |
| 最終ジャッジ日時 | 2026-02-06 22:37:23 |
| 合計ジャッジ時間 | 29,212 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 14 WA * 27 |
ソースコード
//Compile Options
# pragma GCC target("avx2")
# pragma GCC optimize("O3")
# pragma GCC optimize("unroll-loops")
//libraries
#include <bits/stdc++.h>
//templates
// ---------- 基本 ----------
#define ll long long
#define ull unsigned long long
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>
// ---------- for 系 ----------
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;i--)
#define repi(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
// ---------- コンテナ操作 ----------
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
// ---------- sort ----------
#define srt(x) sort(all(x))
#define rsrt(x) sort(rall(x))
// ---------- sum ----------
#define sum(x) std::reduce(all(x))
// ---------- 出力補助 ----------
#define yes cout << "Yes\n"
#define no cout << "No\n"
#define YES cout << "YES\n"
#define NO cout << "NO\n"
#define print(a) cout << (a) << endl
// その他
#define append push_back
using namespace std;
template <class T>
void println_decimal(T value, int digits) {
std::cout << std::fixed << std::setprecision(digits) << value << '\n';
}
//累積和
template <class T = long long>
struct CumulativeSum {
private:
// pref[i] = 先頭から i 個分の和
std::vector<T> pref;
public:
CumulativeSum() {
pref.push_back(T(0)); // pref[0] = 0
}
// 要素を末尾に追加
void push_back(T x) {
pref.push_back(pref.back() + x);
}
// 区間 [l, r] の和を返す
T range_sum(int l, int r) const {
//assert(0 <= l && l <= r && r < (int)pref.size());
if (l<0 && r<0) return 0;
if (l>=(int)pref.size()-1) return 0;
if (l<0) l=0;
if (r>=(int)pref.size()-1) r=(int)pref.size()-2;
return pref[r+1] - pref[l];
}
// 現在の要素数
int size() const {
return (int)pref.size() - 1;
}
};
//使い方
// CumulativeSum<long long> cs;
// cs.push_back(3);
// cs.push_back(5);
// cs.push_back(2);
// // [0,2] = 3+5+2
// cs.range_sum(0, 2); // 10
// // [-5,1] → [0,1]
// cs.range_sum(-5, 1); // 8
// // [2,10] → [2,2]
// cs.range_sum(2, 10); // 2
// // 完全に外
// cs.range_sum(5, 7); // 0
// const int N = 2*pow(10,4);
// vector<bool> isp(N+1, true);
// void sieve() {
// isp[0] = false;
// isp[1] = false;
// for (int i=2; pow(i,2)<=N; i++) {
// if (isp[i]) for(int j=2; i*j<=N; j++) isp[i*j] = false;
// }
// }
//素因数分解
// const int N = 200000; // 必要に応じて変更
// vector<int> minp(N + 1);
// 最小素因数の前計算
// void sieve_minp() {
// for (int i = 0; i <= N; i++) minp[i] = i;
// minp[0] = 0;
// minp[1] = 1;
// for (int i = 2; i * i <= N; i++) {
// if (minp[i] == i) { // i が素数
// for (int j = i * i; j <= N; j += i) {
// if (minp[j] == j) minp[j] = i;
// }
// }
// }
// }
// // x の素因数分解を返す
// // 戻り値: {素因数, 指数} の vector
// vector<pair<ll, ll>> pfWithMinp(ll x) {
// vector<pair<ll, ll>> res;
// while (x > 1) {
// ll p = minp[x];
// ll cnt = 0;
// while (x % p == 0) {
// x /= p;
// cnt++;
// }
// res.push_back({p, cnt});
// }
// return res;
// }
ll exp10(int n){
ll ans= 1;
rep(i,n){
ans*=10;
}
return ans;
}
unsigned GetDigit(unsigned num){
unsigned digit = 0;
while(num != 0){
num /= 10;
digit++;
}
return digit;
}
struct triplet
{
/* data */
ll first;
ll second;
ll third;
};
struct Eratosthenes {
// テーブル
vector<bool> isprime;
// 整数 i を割り切る最小の素数
vector<int> minfactor;
// コンストラクタで篩を回す
Eratosthenes(int N) : isprime(N+1, true),
minfactor(N+1, -1) {
// 1 は予めふるい落としておく
isprime[1] = false;
minfactor[1] = 1;
// 篩
for (int p = 2; p <= N; ++p) {
// すでに合成数であるものはスキップする
if (!isprime[p]) continue;
// p についての情報更新
minfactor[p] = p;
// p 以外の p の倍数から素数ラベルを剥奪
for (int q = p * 2; q <= N; q += p) {
// q は合成数なのでふるい落とす
isprime[q] = false;
// q は p で割り切れる旨を更新
if (minfactor[q] == -1) minfactor[q] = p;
}
}
}
// pair (素因子, 指数) の vector を返す
vector<pair<int,int>> factorize(int n) {
vector<pair<int,int>> res;
while (n > 1) {
int p = minfactor[n];
int exp = 0;
// n で割り切れる限り割る
while (minfactor[n] == p) {
n /= p;
++exp;
}
res.emplace_back(p, exp);
}
return res;
}
// 高速約数列挙
vector<int> divisors(int n) {
vector<int> res({1});
// n を素因数分解 (メンバ関数使用)
auto pf = factorize(n);
// 約数列挙
for (auto p : pf) {
int s = (int)res.size();
for (int i = 0; i < s; ++i) {
int v = 1;
for (int j = 0; j < p.second; ++j) {
v *= p.first;
res.push_back(res[i] * v);
}
}
}
return res;
}
};
int main() {
ll N;
cin >> N;
Eratosthenes er(200001);
vector<ll> A(N);
rep(i,N){
cin >> A[i];
A[i]--;
}
//添字・中身でループ検出
vector<bool> visited(N,false);
vector<vector<ll>> loops;
ll ans = 0;
rep(i,N){
if(visited[i]) continue;
vector<ll> loop;
ll cnt = 0;
ll cur = i;
while(!visited[cur]){
visited[cur] = true;
loop.push_back(cur);
cur = A[cur];
cnt++;
}
loops.push_back(loop);
ans += cnt -1;
}
vector<int> res(N,0);
vector<int> dv;
rep(i,loops.size()){
set<int> unique_divisors;
rep(j,loops[i].size()){
// cout << loops[i][j] << " ";
dv = er.divisors(abs(loops[i][j]-loops[i][(j+1)%loops[i].size()]));
rep(k,dv.size()){
res[dv[k]]++;
unique_divisors.insert(dv[k]);
}
}
for(int d : unique_divisors){
res[d]--;
}
}
rep1(i,res.size()-1){
print(res[i]);
}
}
npnp