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掉。

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

代码(神奇式子):

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <cstring>
  6. #include <algorithm>
  7. #define LL long long
  8. #define N 1000000007
  9.  
  10. using namespace std;
  11.  
  12. //快速幂
  13. //O(logn)
  14. LL quickPower(LL x, int n)
  15. {
  16. x %= N;
  17. LL a = ;
  18. while (n)
  19. {
  20. a *= n& ? x : ;
  21. a %= N;
  22. n >>= ;
  23. x = (x*x) % N;
  24. }
  25. return a;
  26. }
  27.  
  28. LL c[], a[], inv[];
  29. int n, d;
  30.  
  31. void init()
  32. {
  33. //***预处理所有i在质数MOD下的逆元
  34. inv[] = ;
  35. for (int i = ; i <= ; i++)
  36. inv[i] = inv[N%i]*(N-N/i) % N;
  37.  
  38. a[] = ;
  39. for (int i = ; i <= ; ++i)
  40. a[i] = (inv[i]*a[i-]) % N;
  41. }
  42.  
  43. void work()
  44. {
  45. if (n >= d)
  46. {
  47. printf("%lld\n", quickPower(, d));
  48. return;
  49. }
  50. LL now = d, ans = ;
  51. c[] = ;
  52. for (int i = ; i <= n; ++i)
  53. {
  54. c[i] = (now*c[i-]) % N;
  55. now--;
  56. }
  57. for (int i = ; i <= n; ++i)
  58. {
  59. ans += c[i]*a[i];
  60. ans %= N;
  61. }
  62. printf("%lld\n", ans);
  63. }
  64.  
  65. int main()
  66. {
  67. //freopen("test.in", "r", stdin);
  68. //freopen("test.out", "w", stdout);
  69. init();
  70. int T;
  71. scanf("%d", &T);
  72. for (int times = ; times <= T; ++times)
  73. {
  74. printf("Case #%d: ", times);
  75. scanf("%d%d", &n, &d);
  76. work();
  77. }
  78. return ;
  79. }

代码二(exgcd):

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #include <queue>
  7. #define FOR(i,x,y) for(int i = x;i < y;i ++)
  8. #define IFOR(i,x,y) for(int i = x;i > y;i --)
  9. #define ll long long
  10. #define N 111111
  11. #define D 1111111
  12. #define MOD 1000000007
  13.  
  14. using namespace std;
  15.  
  16. ll c[N],mu[N];
  17. ll n,d;
  18.  
  19. ll quickpow(ll a,ll n,ll m){
  20. ll ans=;
  21. while(n){
  22. if(n&) ans = (ans*a)%m;
  23. a = (a*a)%m;
  24. n>>=;
  25. }
  26. return ans;
  27. }
  28.  
  29. void ex_gcd(ll a,ll b,ll& d,ll& x,ll& y){
  30. if(!b) {d = a;x = ;y = ;return;}
  31. ex_gcd(b,a%b,d,y,x);
  32. y -= x*(a/b);
  33. }
  34.  
  35. ll inv(ll a,ll n){
  36. ll d,x,y;
  37. ex_gcd(a,n,d,x,y);
  38. return d == ? (x+n)%n : -;
  39. }
  40.  
  41. void init(){
  42. FOR(i,,N){
  43. mu[i] = inv(i,MOD);
  44. }
  45. }
  46.  
  47. void C(){
  48. c[] = ;
  49. FOR(i,,n+){
  50. ll tem = (d+-i)*mu[i]%MOD;
  51. c[i] = (tem*c[i-]) % MOD;
  52. }
  53. }
  54.  
  55. ll solve(){
  56. ll res = ;
  57. FOR(i,,n+){
  58. res += c[i];
  59. res %= MOD;
  60. }
  61. return res;
  62. }
  63.  
  64. int main()
  65. {
  66. //freopen("test.in","r",stdin);
  67. int t,tCase = ;
  68. scanf("%d",&t);
  69. init();
  70. while(t--){
  71. printf("Case #%d: ",++tCase);
  72. scanf("%lld%lld",&n,&d);
  73. ll ans = ;
  74. if(n >= d){
  75. ans = quickpow(,d,MOD);
  76. }
  77. else{
  78. C();
  79. ans = solve();
  80. }
  81. printf("%lld\n",ans);
  82. }
  83. return ;
  84. }

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. java 接口回调

    学习自:http://blog.csdn.net/xiaanming/article/details/8703708/ http://hellosure.iteye.com/blog/1130176 ...

  2. java.util.Date和java.sql.Date之间的转换

    java.util.Date是在除了SQL语句的情况下面使用的.java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分它 们都有getTime方法返回毫秒数,自然就可以直接构建. ...

  3. Android Calendar的学习与运用

    [java]mport java.text.DateFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; ...

  4. android利用apkplug框架实现主应用与插件通讯(传递随意对象)实现UI替换

    时光匆匆,乍一看已半年过去了,经过这半年的埋头苦干今天最终有满血复活了. 利用apkplug框架实现动态替换宿主Activity中的UI元素.以达到不用更新应用就能够更换UI样式的目的. 先看效果图: ...

  5. 读懂JVM垃圾收集日志

    JVM垃圾收集搞懂原理很重要,但是连垃圾收集的日志都不懂,这tmd还分析个屁的问题啊,典型的空有理论知识,动手实践为零.本篇就来具体的学习一下JVM中的垃圾收集日志. 第一步,垃圾收集的选项 图1 J ...

  6. maven新建项目报错

    创建了一个maven项目,报错 Errors occurred during the build. Errors running builder 'Maven Project Builder' on ...

  7. Android-Android Studio 3.0找不到Android Device Monitor

    原文:https://blog.csdn.net/yuanxiang01/article/details/80494842?utm_source=copy   为什么Android Studio 3. ...

  8. Windows上搭建Kafka

    搭建环境: 1,安装JDK JAVA_HOME: C:\Program Files (x86)\Java\jre1.8.0_60(这个是默认安装路径,如果安装过程中更改了安装目录,把更改后的路径填上就 ...

  9. python 基础 7.8 json--下

      一. 文件和json 之间的转换 1. json.dump()   #/usr/bin/python #coding=utf-8 #@Time   :2017/11/13 0:12 #@Authe ...

  10. rtsp转rtmp、hls网页直播服务器EasyNVR前端兼容性调试:ie下的 pointer-events- none

    发现问题: 之前在做EasyNVR 的web页面开发过程中,力求的都是一个播放效果的.功能的展示.对于兼容性也有注意,但有些细节还是难免有所疏忽. 内部测试发现:由于我们是流媒体的实时视频直播,在we ...