トピック
一連の考え
この問題は明らかに分割可能なブロック問題です。
表には同じ値が連続して現れ、同じ値で割った区間積が整数で割り切れるブロックになります。
割り切れる性質により、1 から n までの配列テーブルは値に応じて異なるブロックに分割でき、ブロックの数は n よりもはるかに少なくなります。
このプロパティを使用して、各ブロックの特定の左右の端点がどこにあるかを推測できれば、この問題はすぐに解決できます。
特定のブロックの左端点 L がわかっていると仮定すると、ブロックの右端点 R を解く必要があります。
ブロックの値を K とすると、k = ⌊ n/ L ⌋
区間 [L, R] 内の各数値 i は ⌊ n/ i ⌋=k を満たすため
したがって、右側の境界 R は、条件 i*K<=N を満たす最大の i です。つまり、R=⌊n/k⌋=⌊n/(⌊n/ L⌋) ⌋
コード
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,l = 1,r,k,ans;
signed main()
{
cin>>n;
while(l <= n)
{
r = n / (n / l);
k = n / l;
ans += (r - l + 1) * k;
l = r + 1;
}
cout<<ans;
return 0;
}