您的位置:首页 > 其它

CCF有趣的数(快速幂,递推)

2016-04-09 17:35 246 查看

问题描述

  我们把一个数称为有趣的,当且仅当:

  1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。

  2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。

  3. 最高位数字不为0。

  因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。

  请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。

输入格式

  输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。

输出格式

  输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。

样例输入

4

样例输出

3

题解

一开始看这题真的是毫无头绪,后来尝试从一些很简单的问题入手,发现这个数只能以2开头,以1或3结尾,情况以下子少了很多,于是看看能不能递推,思路如下:

- 设长度为n(n>=4)的有趣的数个数为a

- 考察a[n+1],

- 若这个数以1结尾

- 若前n位有0123,该情况数是a

- 若前n位没有1,设第一个3出现的位数是k(1≤k≤n-1,从左往右从1开始),该种情况方法数为2k−1×2n−k−1−1=2n−2−12^{k-1}×2^{n-k-1}-1=2^{n-2}-1,于是总的方法数为(n-1)(2n−2−12^{n-2}-1)

- 若这个数以3结尾

- 若前n位有0123,该情况数是a

- 若前n位没有3,情况略有不同,设第一个1出现的位数是k(2≤k≤n-1),该种情况方法数为(2k−1−1)×2n−k−1=2n−1−2n−k−1(2^{k-1}-1)×2^{n-k-1}=2^{n-1}-2^{n-k-1},于是总的方法数为∑n−1k=2(2n−1−2n−k−1)=(n−3)×2n−2+1\sum_{k=2}^{n-1}(2^{n-1}-2^{n-k-1})=(n-3)×2^{n-2}+1

- 综上,a[n+1]=2a
+(n-2)*2n−12^{n-1}-n+2

- 但是直接这么算,n稍微大一点就会溢出,因此要随时取模

/*a[n+1]=2a
+(n-2)2^(n-1)-n+2*/
#include<stdio.h>
#define m 1000000007
long long Pow(int n)/*计算2^n mod m*/
{
if (n==1)
return 2;
long long half;
half=Pow(n/2);
if ((n&1)==0)
return (half*half)%m;
else
return (((half*half)%m)*2)%m;
}
int main(void)
{
long long a=3;
int i,n;
scanf("%d",&n);
for (i=4;i<n;i++)
a=(a*2+(i-2)*Pow(i-1)-i+2)%m;/*可以保证在取余之前不会溢出,如果是int的话,(i-2)*Pow(i-1)可能会溢出*/
printf("%lld",a);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: