4=1+1+1+1
4=1+1+2
4=1+2+1
4=2+1+1
4=1+3
4=2+2
4=3+1
4=4
totally 8 ways. Actually, we will have f(n)=2 (n-1) after observations.
Given a pair of integers n and k, your task is to figure out how many times that the integer k occurs in such 2 (n-1) ways. In the example above, number 1 occurs for 12 times, while number 4 only occurs once.
Each test case contains two integers n and k(1≤n,k≤10 9).
2 4 2 5 5
5 1
题中给的2^(n-1)很有用
首先先转化问题,求5中2的个数等于求4中1的个数,求5中3的个数等于求4中2的个数,等于求3中1的个数,所有问题都可以转化为求n中1的个数。
下面求n中1的个数:
先写出3的分解情况:(4种)
1 1 1
1 2
2 1
3
再写出4的分解情况:(8种)
1 1 1 1
1 2 1
2 1 1
3 1
1 1 2
1 3
2 2
4
注意我写的顺序,前4行是在3的基础上末尾添1,后4行是在3的基础上末尾加1。
注意到4的情况是3的两倍,而且这样添加不会重复,所以这个思路是可行的。
那么找递推关系:
发现4的情况的前一半是3的情况加3的行数,即A(n)=A(n-1)+2^(n-2)........(没推完呢)
再看4的后一半情况,1的个数等于3中1的个数减去3中末尾是1的个数,由上述推的过程可看出每个数有一半情况末尾是1,
所以A(n)=A(n-1)-0.5*2^(n-2)
综合起来得到一个递推关系:
A(n)=2*A(n-1)+2^(n-3)
下面要考虑算法,打表的话数据太大,不能打,所以要推出方程的一般形式直接算,
中间队友推出一个式子:A(n)=2^n+n*2^(n-3)
但是.......式子是对的,带到递推式里也成立,但是........数据带进去不对!!!为什么???搞了半天还是没搞懂
后来另一个队友推出一个以A3为基础的关系式:An=2^(n-3)*A3+(n-3)*2^(n-3)
首先这个式子是对的,而且测试了很多样例也都对,但是一直WA,还是没搞懂为什么!!!
那么......换方法吧。
队友又推出一个以A2为基础的式子:An=2^(n-2)*A2+(n-2)*2^(n-3)
这回终于A了
这道题总的来说思维还是很不错的,但是中间数据可能有些问题,所以这题很神奇
(AC代码本来想用欧拉定理的A ^ B % C =A ^( B % ψ(C)+ψ(C) ) % C,但是没用也过了)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MOD 1000000007
typedef long long LL;
using namespace std;
LL qpow(LL m,LL n,LL k)
{
LL b=1;
while(n>0)
{
if(n&1)b=(b*m)%k;
n=n>>1;
m=(m*m)%k;
}return b;
}
LL phi(LL n)
{
LL i,rea=n;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
{
rea=rea-rea/i;
while(n%i==0)n/=i;
}
}
if(n>1)
rea=rea-rea/n;
return rea;
}
int main()
{
LL n,k;
int t;
LL ph=phi(MOD);
scanf("%d",&t);
while(t--)
{ LL ans;
scanf("%lld%lld",&n,&k);
if(n<k)ans=0;
if(n==k)ans=1;
else
{
LL a3=5;
LL m=n-k+1;
if(m==2)
ans=2;
else
{
ans=((2*qpow(2,m-2,MOD)%MOD)+(m-2)*qpow(2,m-3,MOD)%MOD)%MOD;
}
}printf("%lld\n",ans);
}
return 0;
}