欢迎光临
我们一直在努力

折返跑【牛客tracker & 每日一题】

折返跑

时间限制:1 秒 空间限制:512M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多! 在这里插入图片描述


题目描述

折返跑是一种跑步运动形式,运动者从一侧的杆子出发,跑向另一侧的杆子,绕过杆子跑回起点,绕过起点的杆子再跑向另一侧,不断重复这一过程。这种运动形式有助于高效利用空间,运动者可以在有限的区域内进行无限的锻炼。

了解了折返跑的运动方法后,Zaoly 不屑道:"哼,杆子不动的折返跑没有灵魂,杆子不断移动的才有意思!"说干就干,他立即进行了一场移动杆折返跑运动。

上体育课了!今天的项目是折返跑,笔直的跑道可以看作是一条数轴。跑道上有

n

n

n 个位点,其中,老师在

1

1

1 点和

n

n

n 点处各放了两根杆子,称为左杆和右杆,作为折返跑的折返点。

老师规定,今天一共需要跑

m

m

m 趟。我们认为,从一根杆子开始,跑到另一根杆子结束为一趟。显然,一共需要进行

m

−

1

m – 1

m−1 次折返。Zaoly 偶然发现,杆子是可推动的,所以他有了一个大胆的想法——

  • 每次跑到右杆折返后,都需要把右杆向左推动一段距离(大于

    0

    0

    0),但仍保证右杆位于整数点,且在左杆的右边(不能与左杆重合);

  • 每次跑到左杆折返后,都需要把左杆向右推动一段距离(大于

    0

    0

    0),但仍保证左杆位于整数点,且在右杆的左边(不能与右杆重合);

现在,给出整数

n

n

n 和

m

m

m 的值,请问 Zaoly 一共有多少种不同的推杆方法?由于答案可能很大,请将答案对

(

10

9

+

7

)

(10^9 + 7)

(109+7) 取模后输出。注意,每次折返时都需要推杆,如果某一轮无法推动,则这一轮推杆非法。


输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数

T

 

(

1

≤

T

≤

10

4

)

T\\ (1 \\le T \\le 10^4)

T (1≤T≤104) 代表数据组数,每组测试数据描述如下:

对于每一组测试数据,输入两个整数

n

,

m

 

(

1

≤

m

<

n

≤

10

6

)

n, m\\ (1 \\le m < n \\le 10^6)

n,m (1≤m<n≤106) 代表位点的数量、折返跑的趟数。


输出描述

对于每组数据,在一行上输出一个整数代表合法的推杆方法种类数。由于答案可能很大,请将答案对

(

10

9

+

7

)

(10^9 + 7)

(109+7) 取模后输出。


示例 1

输入:

3
4 3
5 3
100 1

输出:

1
3
1

说明:

对于第一组测试数据,有且仅有唯一的推杆方法:

  • 在第一次折返时(位于右杆),将右杆向左推一个位点;随后在第二次折返时(位于左杆),将左杆向右推一个位点;

对于第二组测试数据,有以下三种推杆方法:

  • 在第一次折返时(位于右杆),将右杆向左推一个位点;随后在第二次折返时(位于左杆),将左杆向右推一个位点;
  • 在第一次折返时,将右杆向左推两个位点;随后在第二次折返时,将左杆向右推一个位点;
  • 在第一次折返时,将右杆向左推一个位点;随后在第二次折返时,将左杆向右推两个位点。

对于第三组测试数据,由于只跑一趟,没有折返,所以没有推杆,这也算作一种推杆方法。


数据范围与提示

  • 1

    ≤

    T

    ≤

    10

    4

    1 \\le T \\le 10^4

    1≤T≤104

  • 1

    ≤

    m

    <

    n

    ≤

    10

    6

    1 \\le m < n \\le 10^6

    1≤m<n≤106

  • 答案对

    10

    9

    +

    7

    10^9 + 7

    109+7 取模

  • 核心推导:
  • 记第

    k

    k

    k 次折返的推动距离为

    d

    k

    ≥

    1

    d_k \\ge 1

    dk​≥1(

    k

    =

    1

    ,

    2

    ,

    …

    ,

    m

    −

    1

    k = 1, 2, \\dots, m-1

    k=1,2,…,m−1)。奇数次折返发生在右杆处,使

    R

    R

    R 减小;偶数次折返发生在左杆处,使

    L

    L

    L 增大。于是

    R

    =

    n

    −

    (

    d

    1

    +

    d

    3

    +

    …
     

    )

    ,

    L

    =

    1

    +

    (

    d

    2

    +

    d

    4

    +

    …
     

    )

    R = n – (d_1 + d_3 + \\dots),\\qquad L = 1 + (d_2 + d_4 + \\dots)

    R=n−(d1​+d3​+…),L=1+(d2​+d4​+…)

  • 任何时刻都要求

    L

    <

    R

    L < R

    L<R,即

    1

    +

    (

    d

    2

    +

    d

    4

    +

    …
     

    )

    <

    n

    −

    (

    d

    1

    +

    d

    3

    +

    …
     

    )
      

    ⟺
      

    ∑

    k

    =

    1

    m

    −

    1

    d

    k

    ≤

    n

    −

    2

    1 + (d_2 + d_4 + \\dots) < n – (d_1 + d_3 + \\dots) \\iff \\sum_{k=1}^{m-1} d_k \\le n – 2

    1+(d2​+d4​+…)<n−(d1​+d3​+…)⟺k=1∑m−1​dk​≤n−2

  • 因此方案数就是「

    m

    −

    1

    m-1

    m−1 个正整数之和不超过

    n

    −

    2

    n-2

    n−2」的解数。作代换

    d

    k

    ′

    =

    d

    k

    −

    1

    ≥

    0

    d_k' = d_k – 1 \\ge 0

    dk′​=dk​−1≥0,得

    ∑

    d

    k

    ′

    ≤

    n

    −

    m

    −

    1

    \\sum d_k' \\le n – m – 1

    ∑dk′​≤n−m−1,其非负整数解数为

    (

    (

    n

    −

    m

    −

    1

    )

    +

    (

    m

    −

    1

    )

    m

    −

    1

    )

    =

    (

    n

    −

    2

    m

    −

    1

    )

    \\binom{(n-m-1) + (m-1)}{m-1} = \\binom{n-2}{m-1}

    (m−1(n−m−1)+(m−1)​)=(m−1n−2​)

  • 故答案为

    (

    n

    −

    2

    m

    −

    1

    )

     

    m

    o

    d

     

    (

    10

    9

    +

    7

    )

    \\dbinom{n-2}{m-1} \\bmod (10^9+7)

    (m−1n−2​)mod(109+7)。由于

    n

    ≤

    10

    6

    n \\le 10^6

    n≤106,预处理阶乘与阶乘逆元(

    O

    (

    n

    )

    O(n)

    O(n)),每组询问

    O

    (

    1

    )

    O(1)

    O(1) 回答即可,总复杂度

    O

    (

    max

    ⁡

    n

    +

    T

    )

    O(\\max n + T)

    O(maxn+T)。

解题思路

本题是组合计数问题。通过分析折返跑过程中杆子的移动规律,将推杆方案数转化为正整数解的组合数问题。

1. 问题等价转化
  • 跑道数轴上有左杆初始在位置

    1

    1

    1,右杆初始在位置

    n

    n

    n。共跑

    m

    m

    m 趟,因此有

    m

    −

    1

    m-1

    m−1 次折返。

  • 第

    k

    k

    k 次折返时推动距离记为

    d

    k

    ≥

    1

    d_k \\ge 1

    dk​≥1(整数),

    k

    =

    1

    ,

    2

    ,

    …

    ,

    m

    −

    1

    k = 1, 2, \\dots, m-1

    k=1,2,…,m−1。

    • 奇数次折返发生在右杆处,右杆向左移动,因此右杆位置变为

      n

      −

      (

      d

      1

      +

      d

      3

      +

      …
       

      )

      n – (d_1 + d_3 + \\dots)

      n−(d1​+d3​+…)。

    • 偶数次折返发生在左杆处,左杆向右移动,因此左杆位置变为

      1

      +

      (

      d

      2

      +

      d

      4

      +

      …
       

      )

      1 + (d_2 + d_4 + \\dots)

      1+(d2​+d4​+…)。

  • 任意时刻必须保证左杆在右杆左边(不能重合),即:

    1

    +

    (

    d

    2

    +

    d

    4

    +

    …
     

    )

    <

    n

    −

    (

    d

    1

    +

    d

    3

    +

    …
     

    )

    1 + (d_2 + d_4 + \\dots) < n – (d_1 + d_3 + \\dots)

    1+(d2​+d4​+…)<n−(d1​+d3​+…) 移项得:

    ∑

    k

    =

    1

    m

    −

    1

    d

    k

    ≤

    n

    −

    2

    \\sum_{k=1}^{m-1} d_k \\le n – 2

    k=1∑m−1​dk​≤n−2

  • 因此问题转化为:求

    m

    −

    1

    m-1

    m−1 个正整数

    d

    1

    ,

    d

    2

    ,

    …

    ,

    d

    m

    −

    1

    d_1, d_2, \\dots, d_{m-1}

    d1​,d2​,…,dm−1​ 之和不超过

    n

    −

    2

    n-2

    n−2 的方案数。

2. 组合数推导
  • 令

    d

    k

    ′

    =

    d

    k

    −

    1

    ≥

    0

    d_k' = d_k – 1 \\ge 0

    dk′​=dk​−1≥0,则:

    ∑

    k

    =

    1

    m

    −

    1

    d

    k

    ′

    ≤

    n

    −

    2

    −

    (

    m

    −

    1

    )

    =

    n

    −

    m

    −

    1

    \\sum_{k=1}^{m-1} d_k' \\le n – 2 – (m-1) = n – m – 1

    k=1∑m−1​dk′​≤n−2−(m−1)=n−m−1

  • 设

    S

    =

    ∑

    k

    =

    1

    m

    −

    1

    d

    k

    ′

    S = \\sum_{k=1}^{m-1} d_k'

    S=∑k=1m−1​dk′​,则

    0

    ≤

    S

    ≤

    n

    −

    m

    −

    1

    0 \\le S \\le n – m – 1

    0≤S≤n−m−1。对于固定的

    S

    S

    S,非负整数解的数量为

    (

    S

    +

    (

    m

    −

    1

    )

    −

    1

    m

    −

    2

    )

    \\binom{S + (m-1) – 1}{m-2}

    (m−2S+(m−1)−1​)。

  • 对所有可能的

    S

    S

    S 求和,利用组合恒等式:

    ∑

    S

    =

    0

    n

    −

    m

    −

    1

    (

    S

    +

    m

    −

    2

    m

    −

    2

    )

    =

    (

    n

    −

    2

    m

    −

    1

    )

    \\sum_{S=0}^{n-m-1} \\binom{S + m – 2}{m – 2} = \\binom{n – 2}{m – 1}

    S=0∑n−m−1​(m−2S+m−2​)=(m−1n−2​)

  • 因此答案为

    (

    n

    −

    2

    m

    −

    1

    )

     

    m

    o

    d

     

    (

    10

    9

    +

    7

    )

    \\dbinom{n-2}{m-1} \\bmod (10^9+7)

    (m−1n−2​)mod(109+7)。

3. 算法实现
  • 由于

    n

    ≤

    10

    6

    n \\le 10^6

    n≤106,可以预处理阶乘

    f

    [

    i

    ]

    f[i]

    f[i] 和阶乘逆元

    i

    n

    v

    f

    [

    i

    ]

    invf[i]

    invf[i],以便

    O

    (

    1

    )

    O(1)

    O(1) 计算组合数。

  • 预处理:
    • f

      [

      0

      ]

      =

      i

      n

      v

      f

      [

      0

      ]

      =

      1

      f[0] = invf[0] = 1

      f[0]=invf[0]=1

    • f

      [

      i

      ]

      =

      f

      [

      i

      −

      1

      ]

      ×

      i
       

      m

      o

      d

       

      M

      O

      D

      f[i] = f[i-1] \\times i \\bmod MOD

      f[i]=f[i−1]×imodMOD

    • 用快速幂求

      f

      [

      N

      −

      1

      ]

      f[N-1]

      f[N−1] 的逆元,然后倒推

      i

      n

      v

      f

      [

      i

      ]

      =

      i

      n

      v

      f

      [

      i

      +

      1

      ]

      ×

      (

      i

      +

      1

      )
       

      m

      o

      d

       

      M

      O

      D

      invf[i] = invf[i+1] \\times (i+1) \\bmod MOD

      invf[i]=invf[i+1]×(i+1)modMOD

  • 组合数计算:

    C

    (

    a

    ,

    b

    )

    =

    f

    [

    a

    ]

    ×

    i

    n

    v

    f

    [

    b

    ]

    ×

    i

    n

    v

    f

    [

    a

    −

    b

    ]
     

    m

    o

    d

     

    M

    O

    D

    C(a, b) = f[a] \\times invf[b] \\times invf[a-b] \\bmod MOD

    C(a,b)=f[a]×invf[b]×invf[a−b]modMOD

  • 对于每组询问,直接输出

    C

    (

    n

    −

    2

    ,

    m

    −

    1

    )

    C(n-2, m-1)

    C(n−2,m−1)。

4. 复杂度分析
  • 时间复杂度:预处理

    O

    (

    N

    )

    O(N)

    O(N),每组询问

    O

    (

    1

    )

    O(1)

    O(1)。总复杂度

    O

    (

    max

    ⁡

    n

    +

    T

    )

    O(\\max n + T)

    O(maxn+T),

    N

    =

    10

    6

    N = 10^6

    N=106,

    T

    ≤

    10

    4

    T \\le 10^4

    T≤104,完全可行。

  • 空间复杂度:需要存储阶乘和逆元数组,

    O

    (

    N

    )

    O(N)

    O(N)。

总结

通过分析杆子移动的约束,将推杆方案数转化为“

m

−

1

m-1

m−1 个正整数之和不超过

n

−

2

n-2

n−2”的解数,再利用组合恒等式得到答案

(

n

−

2

m

−

1

)

\\binom{n-2}{m-1}

(m−1n−2​)。预处理阶乘和逆元后,每组询问可在

O

(

1

)

O(1)

O(1) 时间内回答。

代码内容

#include <bits/stdc++.h>
using namespace std;

#define endl '\\n'
typedef long long ll;
typedef unsigned long long ull;
typedef vector<vector<ll>> vvt;
typedef pair<ll,ll> pll;
const ll N=1e6+10;
const ll mod=1e9+7;
const ll inf=1e18;

ll n,m,f[N],invf[N],ans;

ll ksm(ll x,ll n)
{
ll res=1;
while(n)
{
if(n&1)res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}

ll inv(ll x)
{
return ksm(x,mod–2);
}

void init()
{
f[0]=invf[0]=1;
for(ll i=1;i<N;i++)f[i]=f[i–1]*i%mod;
invf[N–1]=inv(f[N–1]);
for(ll i=N–2;i>0;i—)invf[i]=invf[i+1]*(i+1)%mod;
}

ll C(ll a,ll b)
{
return f[a]*invf[b]%mod*invf[a–b]%mod;
}

void solve()
{
cin>>n>>m;
cout<<C(n–2,m–1)<<"\\n";
}

int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
init();
int T;
cin>>T;
while(T—)solve();
return 0;
}

赞(0)
未经允许不得转载:171主机测评 » 折返跑【牛客tracker & 每日一题】
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址