#F. 割り切れる和

トピック


一連の考え

この問題は明らかに分割可能なブロック問題です。

表には同じ値が連続して現れ、同じ値で割った区間積が整数で割り切れるブロックになります。

割り切れる性質により、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;
}

おすすめ

転載: blog.csdn.net/weq2011/article/details/129191087