CF717A Festival Organization

题目大意

一个合法的串定义为:长度在 $[l,r]$ 之间,且只含 0,1,并且不存在连续 $2$ 个或更多的 $0$。

现在要选出 $k$ 个长度相同的合法的串,问有几种选法,答案模 $10^9+7$。

$ 1 \leq k \leq 200$,$1 \leq l \leq r \leq 10^{18}$

题目分析

显而易见的我们要求的是一个形如 $ \sum_{l+2}^{r+2} \binom{f_i}{k}$的东西,其中 $f_i$表示斐波那契数列的第$i$项

我们把上式转化成求$ \sum_{i=1}^{n} \binom{f_i}{k}$,那么我们可以开始推式子了
$$
\sum_{i=1}^n \binom {f_i}{k}
$$

$$
= \frac{1}{k!} \sum_{i=1}^n \sum_{j=1}^k (f_i - j + 1)
$$

$$
= \frac{1}{k!} \sum_{i=1}^n \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} f_i^j
$$

这里用的是下降幂多项式转普通多项式的方法,$\begin{bmatrix}k \\ j\end{bmatrix}$是第一类斯特林数
$$
= \frac{1}{k!} \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} \sum_{i=1}^n f_i^j
$$

$$
= \frac{1}{k!} \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} \sum_{i=1}^n (\frac{1}{\sqrt 5}(\phi^i - \hat{\phi}^i))^j
$$

$$
= \frac{1}{k!} \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} (\frac{1}{\sqrt 5})^j \sum_{i=1}^n (\phi^i - \hat{\phi}^i)^j
$$

$$
= \frac{1}{k!} \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} (\frac{1}{\sqrt 5})^j \sum_{i=1}^n \sum_{l=0}^j (-1)^l \binom{j}{l} \phi^{li} \hat{\phi}^{(j-l)i}
$$

$$
= \frac{1}{k!} \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} (\frac{1}{\sqrt 5})^j \sum_{l=1}^j (-1)^l \binom{j}{l} \sum_{i=1}^n (\phi^{l} \hat{\phi}^{(j-l)})^i
$$

$$
= \frac{1}{k!} \sum_{j=1}^k (-1)^{k-j} \begin{bmatrix}k \\ j\end{bmatrix} (\frac{1}{\sqrt 5})^j \sum_{l=1}^j (-1)^l \binom{j}{l} \frac{\phi^{l} \hat{\phi}^{(j-l)}({1-\phi^{l} \hat{\phi}^{(j-l)})^n}}{1-\phi^{l}\hat{\phi}^{(j-l)}}
$$

大概就是这样一个式子,接下来就可以在 $O(k^2)$的时间内计算这个东西了

但是我们发现,浮点数显然无法承担这么复杂的计算任务,怎么处理 $\phi$和$\hat{\phi}$呢?

类似于 $a + bi$的形式,我们搞一个$a+b\sqrt{5}$出来,接下来就可以用这个数域处理上面的式子了

最后会附上草稿纸的原图,如果发现有和上面不一样的请联系我,谢谢!

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <bits/stdc++.h>

#define R register
#define ll long long
#define sqr(x) ((x) * (x))
#define sum(a, b, mod) (((a) + (b)) % mod)
#define meow(cat...) fprintf(stderr, cat)

const ll MaxN = 2e3 + 10;
const ll mod = 1e9 + 7;

ll add(ll a, ll b) { return a + b >= mod ? a + b - mod : a + b; }
ll dec(ll a, ll b) { return a - b < 0 ? a - b + mod : a - b; }
ll pw(ll a, ll b)
{
ll ret = 1;
while (b)
{
if (b & 1)
ret = ret * a % mod;
a = a * a % mod, b >>= 1;
}
return ret;
}

struct num
{
ll a, b;
num(ll a = 0, ll b = 0) : a(a), b(b) {}
num operator+(const num &x) const { return num(add(a, x.a), add(b, x.b)); }
num operator+(const ll &x) const { return num(add(a, x), b); }
inline num operator-(const num &x) const { return num(dec(a, x.a), dec(b, x.b)); }
inline num operator-(const ll &x) const { return num(dec(a, x), b); }
inline num operator*(const num &x) const
{
num res;
res.a = (a * x.a + b * x.b * 5) % mod;
res.b = (a * x.b + b * x.a) % mod;
return res;
}
inline num operator*(const ll &x) const { return num(a * x % mod, b * x % mod); }

friend inline num operator/(const num &x, const num &y)
{
num res, z = y;
if (z.b != 0) z.b = mod - z.b;
res = x * z;
return res * pw(dec(y.a * y.a % mod, y.b * y.b * 5 % mod), mod - 2);
}
} phi = num(500000004, 500000004), iphi = num(500000004, 500000003);

ll n, l, r, k, ifac;
ll c[MaxN][MaxN], s[MaxN][MaxN];

num poww(num a, ll b)
{
num ret = num(1, 0);
while (b)
{
if (b & 1)
ret = ret * a;
a = a * a, b >>= 1;
}
return ret;
}

num suma(num a, ll n) { return (poww(a, n + 1) - a) / (a - 1); }

num query(num x, ll l, ll r)
{
if (x.a == 1 && x.b == 0) return x * (r - l + 1);
return suma(x, r) - suma(x, l - 1);
}

ll func(ll n, ll k)
{
num ans, a = num(0, 400000003);
for (ll j = 0; j <= k; j++)
{
ll b = (((j + k) % 2) ? -1 : 1) * c[k][j] % mod;
num c = poww(phi, j) * poww(iphi, k - j);
b = (b + mod) % mod, ans = ans + query(c, 1, n) * b;
}
a = poww(a, k), ans = ans * a;
return (ans.a % mod + mod) % mod;
}

ll fun(ll n, ll k)
{
ll ans = 0;
for (ll j = 1; j <= k; j++)
{
ll b = (((k - j) % 2) ? -1 : 1) * s[k][j] % mod;
b = (b + mod) % mod, ans = sum(ans, b * func(n, j), mod);
}
return ans;
}

signed main()
{
scanf("%lld%lld%lld", &k, &l, &r), l += 2, r += 2, c[0][0] = s[0][0] = ifac = 1;
for (ll i = 1; i <= k; i++) ifac = ifac * i % mod; ifac = pw(ifac, mod - 2);
for (ll i = 1; i < MaxN; i++)
{
c[i][0] = 1;
for (ll j = 1; j <= i; j++)
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
for (ll i = 1; i < MaxN; i++)
for (ll j = 1; j <= i; j++)
s[i][j] = (ll)(s[i - 1][j] * (i - 1) + s[i - 1][j - 1]) % mod;
printf("%lld\n", (fun(r, k) - fun(l - 1, k) + mod) * ifac % mod);
return 0;
}

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×