Description

Assuming a finite – radius “ball” which is on an N dimension is cut with a “knife” of N-1 dimension. How many pieces will the “ball” be cut into most?
However, it’s impossible to understand the following statement without any explanation.
Let me illustrate in detail.
When N = 1, the “ball” will degenerate into a line of finite length and the “knife” will degenerate into a point. And obviously, the line will be cut into d+1 pieces with d cutting times.
When N = 2, the “ball” will degenerate into a circle of finite radius and the “knife” will degenerate into a line. Likewise, the circle will be cut into (d^2+d+2)/2 pieces with d cutting times.
When N = 3, the “ball” will degenerate into a ball on a 3-dimension space and the “knife” will degenerate into a plane.
When N = 4, the “ball” will degenerate into a ball on a 4-dimension space and the “knife” will degenerate into a cube on a 3 dimension.
And so on.
So the problem is asked once again: Assuming a finite-radius “ball” which is on an N dimension is cut with a “knife” of N-1 dimension. How many “pieces” will the “ball” be cut into most?

Input

The first line of the input gives the number of test cases T. T test cases follow. T is about 300.
For each test case, there will be one line, which contains two integers N, d(1 <= N <= 10^5, 1 <= d <= 10^6).

Output

For each test case, output one line containing “Case #x: y”, where x is the test case number (standing from 1) and y is the maximum number of “pieces” modulo 10^9+7.

Sample Input

3

3 3

3 5

4 5

Sample Output

Case #1: 8

Case #2: 26

Case #3: 31

HINT

Please use %lld when using long long

题目大意就是n维空间切d刀,最多能分成几个部分。

基本上通过推倒三位的大概就能很快推出整个的递推式。

设p(n, d)表示n维空间切d刀。

假设已经切了d-1刀,最后一刀自然切得越多越好。于是最后一刀如果和所有d-1到切的话自然是最好。但是可以逆过来看,相当于d-1到切最后一刀这个n-1维空间。

于是p(n, d) = p(n, d-1) + p(n-1, d-1)

然而这个式子虽然出来了,但是根据n和d的范围打表是不可能的。也不能直接暴力递推求解,自然考虑到可能要直接求表达式。

然而,表达式我求了好久没求出来,不过看了最后表达式后,大概能有以下思路来求通项:

首先有以下事实:

1:手写打表的话:

d->

0

1

2

3

4

5

n

1

1

2

3

4

5

6

2

1

2

4

7

11

16

3

1

2

4

8

15

26

4

1

2

4

8

16

31

5

1

2

4

8

16

32

6

1

2

4

8

16

32

会发现当n >= d时,通项是2^d,其实稍微考虑一下确实如此。因为第一列都是1,自然第二列从第二项开始都是2,同理往后从对角线往后都是乘2,自然是2^d。

2:设p(n, d)的差数列为a(n, d)的话,

自然a(n, d) = p(n, d) – p(n-1, d)

由原式得p(n-1, d) = p(n-1, d-1) + p(n-2, d-1)

三式式消去p得

a(n, d) = a(n, d-1) + a(n-1, d-1)

说明p的差数列也是满足这个递推式,同理p的任意k阶差数列都满足这个式子。

然而让这些差数列最后通项不同的因素自然应该是前几项导致的

有了上面两个结论,于是只用求n < d的情况,可以从下面两个角度考虑

1:利用组合数式子:C(n, m) = C(n-1, m) + C(n-1, m-1),其中C(n, m)表示从n个中取m个。

由于这个式子和题目递推式非常形似。 于是猜测C(n, m)为p的某一阶差数列。根据前几列和前几行的计算,C(n, m)为p的第一阶差数列。于是p(n, d) = sum(C(d, i)) (0 <= i <= n)

2:根据第一个结论:列出第一阶的差数列

d->

0

1

2

3

4

5

n

1

1

2

3

4

5

2

0

0

1

3

6

10

3

0

0

0

1

4

10

4

0

0

0

0

1

5

5

0

0

0

0

0

1

6

0

0

0

0

0

0

基本上可以找规律,发现第一阶差数列是C(n, m)。

然后就是求C(d, i)的和了,由于d很大,考虑C(d, i) = A(d, i) / i!,然后就是求分子和分母在模10^9+7的情况下的商了。自然需要考虑到逆元。

这里对于逆元的处理可以预处理打表,经测试直接在线求exgcd逆元会T掉。

这里预处理用了网上的一个神奇的递推式,还有一种是我大连海事一个同学的做法。

代码(神奇式子):

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#define LL long long
#define N 1000000007 using namespace std; //快速幂
//O(logn)
LL quickPower(LL x, int n)
{
x %= N;
LL a = ;
while (n)
{
a *= n& ? x : ;
a %= N;
n >>= ;
x = (x*x) % N;
}
return a;
} LL c[], a[], inv[];
int n, d; void init()
{
//***预处理所有i在质数MOD下的逆元
inv[] = ;
for (int i = ; i <= ; i++)
inv[i] = inv[N%i]*(N-N/i) % N; a[] = ;
for (int i = ; i <= ; ++i)
a[i] = (inv[i]*a[i-]) % N;
} void work()
{
if (n >= d)
{
printf("%lld\n", quickPower(, d));
return;
}
LL now = d, ans = ;
c[] = ;
for (int i = ; i <= n; ++i)
{
c[i] = (now*c[i-]) % N;
now--;
}
for (int i = ; i <= n; ++i)
{
ans += c[i]*a[i];
ans %= N;
}
printf("%lld\n", ans);
} int main()
{
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
init();
int T;
scanf("%d", &T);
for (int times = ; times <= T; ++times)
{
printf("Case #%d: ", times);
scanf("%d%d", &n, &d);
work();
}
return ;
}

代码二(exgcd):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define FOR(i,x,y) for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)
#define ll long long
#define N 111111
#define D 1111111
#define MOD 1000000007 using namespace std; ll c[N],mu[N];
ll n,d; ll quickpow(ll a,ll n,ll m){
ll ans=;
while(n){
if(n&) ans = (ans*a)%m;
a = (a*a)%m;
n>>=;
}
return ans;
} void ex_gcd(ll a,ll b,ll& d,ll& x,ll& y){
if(!b) {d = a;x = ;y = ;return;}
ex_gcd(b,a%b,d,y,x);
y -= x*(a/b);
} ll inv(ll a,ll n){
ll d,x,y;
ex_gcd(a,n,d,x,y);
return d == ? (x+n)%n : -;
} void init(){
FOR(i,,N){
mu[i] = inv(i,MOD);
}
} void C(){
c[] = ;
FOR(i,,n+){
ll tem = (d+-i)*mu[i]%MOD;
c[i] = (tem*c[i-]) % MOD;
}
} ll solve(){
ll res = ;
FOR(i,,n+){
res += c[i];
res %= MOD;
}
return res;
} int main()
{
//freopen("test.in","r",stdin);
int t,tCase = ;
scanf("%d",&t);
init();
while(t--){
printf("Case #%d: ",++tCase);
scanf("%lld%lld",&n,&d);
ll ans = ;
if(n >= d){
ans = quickpow(,d,MOD);
}
else{
C();
ans = solve();
}
printf("%lld\n",ans);
}
return ;
}

ACM学习历程—SNNUOJ 1116 A Simple Problem(递推 && 逆元 && 组合数学 && 快速幂)(2015陕西省大学生程序设计竞赛K题)的更多相关文章

  1. ACM学习历程—SNNUOJ 1110 传输网络((并查集 && 离线) || (线段树 && 时间戳))(2015陕西省大学生程序设计竞赛D题)

    Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的 ...

  2. ACM学习历程—HDU 5326 Work(树形递推)

    Problem Description It’s an interesting experience to move from ICPC to work, end my college life an ...

  3. ACM学习历程—HDU 5459 Jesus Is Here(递推)(2015沈阳网赛1010题)

    Sample Input 9 5 6 7 8 113 1205 199312 199401 201314 Sample Output Case #1: 5 Case #2: 16 Case #3: 8 ...

  4. AndyQsmart ACM学习历程——ZOJ3872 Beauty of Array(递推)

    Description Edward has an array A with N integers. He defines the beauty of an array as the summatio ...

  5. angry_birds_again_and_again(2014年山东省第五届ACM大学生程序设计竞赛A题)

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2877 题目描述 The problems ca ...

  6. ZZUOJ-1195-OS Job Scheduling(郑州大学第七届ACM大学生程序设计竞赛E题)

    1195: OS Job Scheduling Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 106  Solved: 35 [id=1195&quo ...

  7. ACM学习历程—SNNUOJ 1239 Counting Star Time(树状数组 && 动态规划 && 数论)

    http://219.244.176.199/JudgeOnline/problem.php?id=1239 这是这次陕西省赛的G题,题目大意是一个n*n的点阵,点坐标从(1, 1)到(n, n),每 ...

  8. ACM学习历程—HDU 5443 The Water Problem(RMQ)(2015长春网赛1007题)

    Problem Description In Land waterless, water is a very limited resource. People always fight for the ...

  9. 2013年山东省第四届ACM大学生程序设计竞赛J题:Contest Print Server

    题目描述     In ACM/ICPC on-site contests ,3 students share 1 computer,so you can print your source code ...

随机推荐

  1. php开启pathinfo 模式

    pathinfo 模式 需要 php.ini 开启下面这个参数 cgi.fix_pathinfo=1 path_info模式:http://www.xxx.com/index.php/模块/方法   ...

  2. Linux下实现RAID

    一.实验目的 1.掌握Linux系统下软RAID的实现方法: 2.掌握RAID5的配置过程: 3. 通过实验熟悉RAID.5的特点. 二.实验内容及步骤 1.在VMware中创建一台Linux. 2. ...

  3. redis写磁盘报错Cannot allocate memory

    查看 Redis 日志发现系统在频繁报错: [1821] 10 Nov 09:59:04.086 # Can't save in background: fork: Cannot allocate m ...

  4. Mongodb亿级数据量的性能测试

    进行了一下Mongodb亿级数据量的性能测试,分别测试如下几个项目:   (所有插入都是单线程进行,所有读取都是多线程进行) 1) 普通插入性能 (插入的数据每条大约在1KB左右) 2) 批量插入性能 ...

  5. Javascript文件加载:LABjs和RequireJS

    传统上,加载Javascript文件都是使用<script>标签. 就像下面这样: <script type="text/javascript" src=&quo ...

  6. EasyNVR RTSP转HLS(m3u8+ts)流媒体服务器前端构建之:bootstrap-datepicker日历插件的实时动态展现

    EasyNVR中有对录像进行检索回放的功能,且先抛开录像的回放,为了更好的用户体验过.让用户方便快捷的找到对应通道对应日期的录像视频,是必须的功能. 基于上述的需求,为前端添加一个日历插件,在日历上展 ...

  7. c++中的重载、覆盖和隐藏

    1 重载发生在同一个类内部. 同一个类内部,具有相同的函数名,但是参数列表不同,那么就是重载.因为c++编译器编译时,将函数名和函数列表一起对函数进行了重命名. 2 覆盖和隐藏发生在子类和父类之间. ...

  8. 题解 P3805 【【模板】manacher算法】

    题解 P3805 [[模板]manacher算法] 我们先看两个字符串: ABCCBA ABCDCBA 显然这两字符串是回文的 然而两个串的对称中心的特性不同,第一个串,它的对称中心在两个C中间,然而 ...

  9. GStreamer 从摄像头获取图像 转264

    1.这里有个简单的例子,可以看看GStreamer如何编程的. 2.GStreamer  GstAppSink的官方Document,翻译了一下它的描述部分,点击这里. 3.GStreamer  Gs ...

  10. rails debug

    =debug @thesis config下配置 东西需要重启之后才管用