題目鏈接:傳送門
青青草原上有只羊,他們聚集在包包大人的家裏,舉辦一年一度的表彰大會,在這次的表彰大會中,包包大人讓羊們按自己的貢獻從小到大排成一排,以便於發放獎金。每隻羊都會得到數值在 1~n 的獎金,並且第 只羊的獎金應爲第 只羊的約數(即滿足 )。現在包包大人想知道一共有多少種不同的發放獎金的方式(兩種發放獎金的方式不同是指在兩種發放獎金的方式中存在某隻羊拿到的獎金不同)
輸入格式
一行兩個正整數 n,k,滿足
輸出格式
一行一個整數代表發放獎金的方案對 1000000007 取模的結果
首先我們先寫出一個的大莉dp:
令表示前只羊,且第只羊的獎金爲的方案數。
顯然的方程:
也就是說,(表示狄利克雷卷積,表示常函數。狄利克雷卷積 & 莫比烏斯反演簡介)
又因爲,所以。
所以快速冪一下,大莉求狄利克雷卷積,總複雜度,不知道爲什麼能卡過去……跑得好像還挺快的qwq
毒瘤代碼
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<vector>
#define re register int
#define mod 1000000007
using namespace std;
typedef long long ll;
int read() {
re x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(const int x) {
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int Size=1000005;
const int INF=0x3f3f3f3f;
int n,k,Div[Size],I[Size],ans[Size],tmp[Size];
void mul(int *a,int *b,int *c) { //a卷積b
for(re i=1; i<=n; i++) c[i]=0;
for(re i=1; i<=n; i++) {
int maxj=Div[i];
for(re j=1; j<=maxj; j++) {
c[i*j]=(c[i*j]+(ll)a[i]*b[j])%mod;
}
}
}
int main() {
// freopen("T3.in","r",stdin);
// freopen("3.out","w",stdout);
n=read();
k=read()-1;
// n=k=1e6;
for(re i=1; i<=n; i++) {
I[i]=ans[i]=1;
Div[i]=n/i;
}
int siz=(n+2)<<2;
while(k) {
if(k&1) {
mul(ans,I,tmp);
memcpy(ans,tmp,siz);
}
mul(I,I,tmp);
memcpy(I,tmp,siz);
k>>=1;
}
int tot=0;
for(re i=1; i<=n; i++) {
tot=(tot+ans[i])%mod;
}
printf("%d",tot);
return 0;
}