诶,其实自己在这种推规律上面的题目非常的陌生,基本上很长时间才能做出来,主要的就是自己列举的例子少,然后就是做的题目少,自己没有过多的思路想问题。燥。
拿出解题报告的解释吧。
我们可以特判出n <= k的情况。
对于1 <= k < n,我们可以等效为n个点排成一列,并取出其中的连续k个点。下面分两种
情况考虑:
第一种情况,被选出的不包含端点,那么有(n – k − 1)种情况完成上述操作,剩下未被圈的点
之间还有(n – k − 2)个位置,可以在每个位置断开,所以共2^(n−k−2) ∗ (n−k−1)种方法。
第二种情况,即被选出的包含端点,那么有2种情况,并且剩余共(n – k − 1)个位置,所以共
2 ∗ 2^(n – k − 1)种方法。
总计2 ∗ 2^(n – k − 1) + 2^(n – k − 2) ∗ (n – k − 1) = (n – k + 3) * 2^(n – k − 2)。
贴出代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
using namespace std;
const int MOD = 1000000000 + 7;
int quick_pow(int a, int n)
{
int ans = 1;
while (n)
{
if (n & 1)
{
ans = (long long) ans * a % MOD;
}
a = (long long)a * a % MOD;
n >>= 1;
}
return ans;
}
int main()
{
int T;
int N, K;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &N, &K);
if (N < K)
{
printf("0\n");
}
else if (N - K == 0)
{
printf("1\n");
}
else if (N - K == 1)
{
printf("2\n");
}
else
{
printf("%d\n", (long long)quick_pow(2, N - K - 2) * (N - K + 3) % MOD);
}
}
// system("pause");
return 0;
}