2.1 B 君的四分之一 (viertel)
【题目背景】
因为晚上 B 君不在,B 君决定出?个昨天讲过的题?。
【题目描述】
回忆 ProjectEuler 258 的做法,我们对其通项做出如下修改。
fn = 1(0 ≤ n < k)
fn = ∑ 1≤i≤k fn?i (n ≥ k)
为了让?家写起来不要太难过,结果对 10007 取模。
【输入格式】
输???两个正整数 n,k。
【输出格式】
输出??表?答案。
【样例输入】
10 2
【样例输出】
89
【数据规模与约定】 对于 100% 的数据 1 ≤ n ≤ 109,2 ≤ k ≤ 1000; 对于 30% 的数据 k = 2; 对于 60% 的数据 k ≤ 100;
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
const int N=2007;
const int mod=10007;
typedef long long LL;
using namespace std;
int n,k,res[N],base[N],c[N];
template<typename T> void read(T &x) {
T f=1; x=0; char ch=getchar();
while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar();
if(ch==‘-‘) f=-1,ch=getchar();
for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f;
}
void cal(int a[],int b[]) {
memset(c,0,sizeof(c));
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
(c[i+j]+=(a[i]*b[j]%mod))%=mod;
for(int i=2*k-1;i>=k;i--)
for(int j=1;j<=k;j++)
(c[i-j]+=c[i])%=mod;
for(int i=0;i<k;i++) a[i]=c[i];
}
void ksm(int b) {
while(b) {
if(b&1) cal(res,base);
cal(base,base);
b>>=1;
}
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("viertel.in","r",stdin);
freopen("viertel.out","w",stdout);
#endif
read(n); read(k);
base[1]=1; res[0]=1;
ksm(n);
int ans=0;
for(int i=0;i<k;i++)
(ans+=res[i])%=mod;
printf("%d\n",ans);
return 0;
}