結果
| 問題 | No.2829 GCD Divination |
| コンテスト | |
| ユーザー |
rieaaddlreiuu
|
| 提出日時 | 2024-12-04 22:05:51 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 2,903 bytes |
| コンパイル時間 | 1,964 ms |
| コンパイル使用メモリ | 175,780 KB |
| 実行使用メモリ | 255,308 KB |
| 最終ジャッジ日時 | 2024-12-04 22:06:09 |
| 合計ジャッジ時間 | 18,651 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 33 TLE * 2 |
ソースコード
//さくせん
// N|dに対して\phi(N/d)を前処理で求めておく
// dpがかんたんになる!
#include<bits/stdc++.h>
using namespace std;
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;
}
};
int computeTotient(int n, const vector<pair<int, int>>& factors) {
double result = n; // 初期値をnに設定
for (const auto& factor : factors) {
int p = factor.first; // 素因数
result *= (1.0 - 1.0 / p);
}
return static_cast<int>(result); // 結果を整数に変換
}
double fill_dp(int N,vector<double> &dp,vector<int> &totient){
if(N == 1){
dp[1] = 0.0;
return 0.0;
}
if(dp[N] > -0.5){
return dp[N];
}
double sum_dp = 0.0;
for(int i=2;i*i<=N;i++){
if(N%i == 0){
sum_dp += (double)totient[N/i]*fill_dp(i,dp,totient);
if(N != i*i){
sum_dp += (double)totient[i]*fill_dp(N/i,dp,totient);
}
}
}
return ((double)N+sum_dp)/((double)(N-1));
}
int main(){
int N;
cin >> N;
Eratosthenes er(N);
vector<int> totient(N+1);
vector<double> dp(N+1,-1.0);
for(int i=1;i*i<=N;i++){
if(i == 1){
totient[N] = computeTotient(N,er.factorize(N));
} else if(N%i == 0){
totient[i] = computeTotient(i,er.factorize(i));
totient[N/i] = computeTotient(N/i,er.factorize(N/i));
}
}
cout << fill_dp(N,dp,totient) << endl;
}
rieaaddlreiuu