トピックリンク:ここをクリック
トピックの主なアイデア:
与えられたn、kn、kn 、k计計算関数数:
f(n、k)= {1 if k = 0 ∑ i =1n⌈log2i⌉f(⌊ni⌋、k − 1)ifk≥1f(n、k)= \ begin {cases} 1&if \ k = 0 \\ \ sum_ {i = 1} ^ n \ lceil log_2i \ rceil f(\ lfloor \ frac ni \ rfloor、k-1)&if \ k \ ge 1 \ end {cases}f (n 、k )={{
1∑i = 1n個⌈ L O G2私⌉ F (⌊私n個⌋ 、k−1 )i f k =0i f k ≥1
答えは1e 9 + 7 1e9 +7です1 e 9+7モジュロ
問題分析:
この式を分析すると、f(1、k)= 0(k≥1)f(1、k)= 0(k \ ge 1)であることが明らかです。f (1 、k )=0 (k≥1 ) f(⌊ni⌋、k − 1)f(\ lfloor \ frac ni \ rfloor、k- 1 )
を見つけますf (⌊私n個⌋ 、k−1) 中的 ⌊ n i ⌋ \lfloor \frac ni \rfloor ⌊私n個⌋は典型的なブロックタイプであり、ブロックで処理できます。⌊ni⌋= 1 \ lfloor \ frac ni \ rfloor = 1⌊私n個⌋=1このブロックサイズはn2 \ fracn2です。2n個、このプロパティを使用すると、f(n、k)f(n、k)を取得できます。f (n 、k ) inf(1、x)f(1、x)f (1 、x )はおよそlog 2 nlog_2nですl o g2n(調和系列)
したがって、n≥log2(1 e 8)≥27の場合n \ ge log_2(1e8)\ ge 27n≥l o g2(1 e 8 )≥データへの答え2 7がある0 00
のためのn≤N \ルlog_2(1E8)を2(1 E 8)ログn≤l o g2(1 e 8 ) ⌈log2i⌉\ lceil log_2i \ rceilを列挙できます⌈ L O G2I ⌉、処理ブロック使用F(\ lfloor \ FRAC NI \ rfloor、K-1) - Fを(1⌊NI⌋、k)をf (⌊私n個⌋ 、k−1 )、覚えるだけ+再帰的な解決策
詳細については、コードを参照してください。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<unordered_map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 5e3+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
unordered_map<int,int>mp[27];
int f(int n,int k)
{
if(k >= 27) return 0;
if(mp[k].find(n) != mp[k].end())
return mp[k][n];
if(k == 0) return mp[k][n] = 1;
else {
int& tmp = mp[k][n];
for(int i = 1;(1<<i) <= 2*n;i++)
{
int l = (1<<(i-1))+1,r = min(1<<i,n),rr;
for(int j = l;j <= r;j = rr+1)
{
int pos = n/j;
rr = min(r,n/pos);
tmp = (tmp+1ll*i*(rr-j+1)%mod*f(pos,k-1))%mod;
}
}
return tmp;
}
}
int main()
{
int n = read(),k = read();
printf("%d\n",f(n,k));
return 0;
}