ACM学习历程—SNNUOJ 1116 A Simple Problem(递推 && 逆元 && 组合数学 && 快速幂)(2015陕西省大学生程序设计竞赛K题)
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题)的更多相关文章
- ACM学习历程—SNNUOJ 1110 传输网络((并查集 && 离线) || (线段树 && 时间戳))(2015陕西省大学生程序设计竞赛D题)
Description Byteland国家的网络单向传输系统可以被看成是以首都 Bytetown为中心的有向树,一开始只有Bytetown建有基站,所有其他城市的信号都是从Bytetown传输过来的 ...
- ACM学习历程—HDU 5326 Work(树形递推)
Problem Description It’s an interesting experience to move from ICPC to work, end my college life an ...
- 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 ...
- 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 ...
- angry_birds_again_and_again(2014年山东省第五届ACM大学生程序设计竞赛A题)
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2877 题目描述 The problems ca ...
- 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 ...
- ACM学习历程—SNNUOJ 1239 Counting Star Time(树状数组 && 动态规划 && 数论)
http://219.244.176.199/JudgeOnline/problem.php?id=1239 这是这次陕西省赛的G题,题目大意是一个n*n的点阵,点坐标从(1, 1)到(n, n),每 ...
- 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 ...
- 2013年山东省第四届ACM大学生程序设计竞赛J题:Contest Print Server
题目描述 In ACM/ICPC on-site contests ,3 students share 1 computer,so you can print your source code ...
随机推荐
- java 接口回调
学习自:http://blog.csdn.net/xiaanming/article/details/8703708/ http://hellosure.iteye.com/blog/1130176 ...
- java.util.Date和java.sql.Date之间的转换
java.util.Date是在除了SQL语句的情况下面使用的.java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分它 们都有getTime方法返回毫秒数,自然就可以直接构建. ...
- Android Calendar的学习与运用
[java]mport java.text.DateFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; ...
- android利用apkplug框架实现主应用与插件通讯(传递随意对象)实现UI替换
时光匆匆,乍一看已半年过去了,经过这半年的埋头苦干今天最终有满血复活了. 利用apkplug框架实现动态替换宿主Activity中的UI元素.以达到不用更新应用就能够更换UI样式的目的. 先看效果图: ...
- 读懂JVM垃圾收集日志
JVM垃圾收集搞懂原理很重要,但是连垃圾收集的日志都不懂,这tmd还分析个屁的问题啊,典型的空有理论知识,动手实践为零.本篇就来具体的学习一下JVM中的垃圾收集日志. 第一步,垃圾收集的选项 图1 J ...
- maven新建项目报错
创建了一个maven项目,报错 Errors occurred during the build. Errors running builder 'Maven Project Builder' on ...
- Android-Android Studio 3.0找不到Android Device Monitor
原文:https://blog.csdn.net/yuanxiang01/article/details/80494842?utm_source=copy 为什么Android Studio 3. ...
- Windows上搭建Kafka
搭建环境: 1,安装JDK JAVA_HOME: C:\Program Files (x86)\Java\jre1.8.0_60(这个是默认安装路径,如果安装过程中更改了安装目录,把更改后的路径填上就 ...
- python 基础 7.8 json--下
一. 文件和json 之间的转换 1. json.dump() #/usr/bin/python #coding=utf-8 #@Time :2017/11/13 0:12 #@Authe ...
- rtsp转rtmp、hls网页直播服务器EasyNVR前端兼容性调试:ie下的 pointer-events- none
发现问题: 之前在做EasyNVR 的web页面开发过程中,力求的都是一个播放效果的.功能的展示.对于兼容性也有注意,但有些细节还是难免有所疏忽. 内部测试发现:由于我们是流媒体的实时视频直播,在we ...