タイトルリンク
アイデアとコード
数論ブロック
数論ブロックのテンプレートの質問です
20点
純粋な暴力、直接列挙してから、各数値を判断します\(O(\ sqrt {n})\)、時間の複雑さ\(O(n \ sqrt {n})\)
我々の鼻に列挙されていないことに注意してください\(\ N-SQRT {} \)場合、\(N- \)の約数\(I \)は、正確に正方形に等しい\(N- \) 、ちょうど十分を追加
int x, y, ans;
signed main() {
x = read(), y = read();
for (int i = x; i <= y; i++) {
for (int j = 1; j <= sqrt(i); j++) {
if (!(i % j)) {
if (j * j == i) ans += j;
else ans += j + (i / j);
}
}
}
cout << ans << '\n';
return 0;
}
60ポイント
列挙除数を列挙倍数にすることも暴力的な考えです
簡単に番号を描画する\(I \)で\(\ N-)の合計\(\ lfloor \ FRAC {N } {I} \ rfloor \) A \(I \)倍数、次いで\(I \)で\(\ N-)寄与に\(\ lfloor \ FRAC {N
} {I} \ rfloor * I \) 、我々は最初に決定することができるので、\(1つの\シムYを\)各\(I \)次いで寄与、減算\(1シムX-1 \ \) 各\(I \)寄与
答えが(\和\ limits_ {iは\ = 1} ^ {Y} \ lfloor \ FRAC {Y } {i} \ rfloor * i- \ sum \ limits_ {i = 1} ^ {x-1} \ lfloor \ frac {x-1} {i} \ rfloor * i \)
時間の複雑さ\(O(y)\)
int x, y, ans1, ans2;
signed main() {
x = read(), y = read();
for (int i = 1; i <= y; i++) ans1 += (y / i) * i;
for (int i = 1; i <= x - 1; i++) ans2 += ((x - 1) / i) * i;
cout << ans1 - ans2 << '\n';
return 0;
}
正解
\(n)が\(18 \)であると仮定して、\(\ lfloor \ frac {n} {i} \ rfloor(1 \ leq i \ leq n)\)の規則を見てみましょう。各\(\ lfloor \ frac {n} {i} \ rfloor \)の値は
\(18,9,6,4,3,3,2,2,2,1,1,1,1,1,1,1,1,1 \)
明らかに、多くの\(\ lfloor \ frac {n} {i} \ rfloor \)の値は同じなので、数論ブロックを使用して
数論ブロック、あなたが見ることができない場合Luckyblockブログ、有益な、詳細な証拠、素晴らしいの話を(実名壁が推奨ひび割れ)
このブログを読み終えたら、(私はそれについて話す必要はないと思います)私たちは話し続けます
明らかに、現在のタスクは、\(\ lfloor \ frac {n} {i} \ rfloor \)の同じ値を持つ区間\(l、r \)を見つけ、\(l \)を\(1 \)に初期化することです。新しい価値のある\(l = r + 1 \)が列挙されるたびに、質問が来ます。\(r \)を求める方法は?
実際、難しいことではありません。上記のブログでも証明されています。証明を彼のブログから移動することであると証明させていただければ、\(r = n /(n / l)\)です。
\(l \)と\(r \)はどちらも理解できるので、答えは毎回どのように蓄積されますか?
する必要があります\(ANS + = \) 、この時点での数は約数の数についてですが、インターバル*と
概数は\(n / l \)です。\(l \)は現在のシーケンスの添え字であるため、\(n / l \)は概数であり、概数の合計も明らかです。つまり、\(\ sum \ limits_ {i = l} ^ {r} i \)、算術シーケンスの合計式を使用すると、この式の答えを見つけることができます\(O(1)\)
算術シーケンスの合計式を書き込む2つの方法
\(a_1 \)は最初の項、\(a_n \)は最後の項、\(d \)は許容誤差、\(S \)は算術シーケンスの合計で、2つの方法で記述できます。
- \(S = na_1 + \ frac {n(n-1)} {2} d \)
- \(S = n(a_1 + a_n)/ 2 \)
最終的な答えは、\(1 \ sim y \)の計算された寄与から\(1 \ sim x-1 \)の寄与を差し引いたものであり、この質問が行われます〜
時間の複雑さ\(O(\ sqrt {n})\)
/*
Author:loceaner
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int A = 1e7 + 11;
const int B = 1e6 + 11;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
int x, y;
inline int sum(int l, int r) {
// return (r - l + 1) * (l + r) / 2;
return 1ll * ((r - l + 1) * l) + 1ll * ((r - l + 1) * (r - l) / 2);
}
inline int solve(int n) {
int ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans += (n / l) * sum(l, r);
}
return ans;
}
signed main() {
x = read(), y = read();
cout << solve(y) - solve(x - 1) << '\n';
return 0;
}