P4936 题解
\(\text{Update}\)(2019.10.05):
- 递推公式推法更详细;
 - 通项公式更新详细版;
 - 单位矩阵的推法更加详细。
 
特别鸣谢 @Smallbasic 苣佬,是他教会了我推递推公式和通项公式。
吐槽:来自同机房巨佬的嘲讽——这道题这么简单,观察法显然可得通项公式
题目分析:
分析题面,原题意思如下:
从\(n\)个互不相同的数中取出某些数,将这些数分成两个集合\(A,B\),这两个集合满足两个条件:
$A $ 集合中的最大的数小于 \(B\)集合中最小的数
$A,B \neq \emptyset $
求共有多少种分法(结果对 \(10^9+7\) 取模)
显然可以发现这题是一道组合数学的题,先手算 \(n \leq 10\) 的数据,在找规律推出公式。我给一下我的思路:
当 \(n=2\) 时,答案显然为1
当 \(n=3\) 时,设这些数为 \(a_1,a_2,a_3\) ,不妨设 \(a_1<a_2<a_3\)
- 当取3个数时,有以下分法:
\[A=\{a_1 \},B=\{a_2,a_3\} \\
A=\{a_1,a_2\},B=\{a_3\}
\] 
共 \(C^3_3 \times (3-1)=2\) 种
- 当取2个数时,有以下分法:
 
\[ A=\{a_1\},B=\{a_2\}\\
A=\{a_1\},B=\{a_3\}\\
A=\{a_2\},B=\{a_3\}
\]共 \(C_3^2 \times (2-1)=3\) 种
综上,当 \(n=3\) 时,有 \(C^3_3 \times (3-1)+C_3^2 \times (2-1)=5\) 种分法。
- 当取3个数时,有以下分法:
 当 \(n=4\) 时,设这些数为 \(a_1,a_2,a_3,a_4\) ,不妨设 \(a_1<a_2<a_3<a_4\)
- 当取4个数时,有以下分法:
 
\[ A=\{a_1\},B=\{a_2,a_3,a_4\}\\
A=\{a_1,a_2\},B=\{a_3,a_4\}\\
A=\{a_1,a_2,a_3\},B=\{a_4\}
\]共 \(C^4_4 \times (4-1)=3\) 种
当取3个数时,有以下分法:
\[A=\{a_1\},B=\{a_2,a_3\}\\
A=\{a_1\},B=\{a_2,a_4\}\\
A=\{a_1\},B=\{a_3,a_4\}\\
A=\{a_2\},B=\{a_3,a_4\}\\
A=\{a_1,a_2\},B=\{a_3\}\\
A=\{a_1,a_2\},B=\{a_4\}\\
A=\{a_1,a_3\},B=\{a_4\}\\
A=\{a_2,a_3\},B=\{a_4\}
\]共 \(C^3_4 \times (3-1)=8\) 种
当取2个数时,有以下分法:
\[A=\{a_1\},B=\{a_2\}\\
A=\{a_1\},B=\{a_3\}\\
A=\{a_1\},B=\{a_4\}\\
A=\{a_2\},B=\{a_3\}\\
A=\{a_2\},B=\{a_4\}\\
A=\{a_3\},B=\{a_4\}
\]共 \(C^2_4 \times (2-1)=6\) 种
综上,当 \(n=4\) 时,有 \(C^4_4 \times (4-1)+C^3_4 \times (3-1)+C^2_4 \times (2-1)=17\) 种分法。
通过数学归纳(找规律),可得公式:
\[F(n)=\sum_{i=1}^{n-1}C^{i+1}_n \cdot i
\]
具体实现的代码就不写了,其他dalao有写。
时间复杂度:\(O(n^2)\)
空间复杂度:\(O(n^2)\)
预计得分:40 points
考虑优化。
发现公式中的瓶颈在于如何快速处理组合数,于是开始推递推公式:
\[\]\begin{aligned}
& F(n+1)-2F(n)\
& =\sum_{i=1}{n}C{i+1}{n+1} \cdot i-(\sum{i=1}{n-1}C{i+1}n \cdot i)\times 2 \
& =\sum{i=1}{n}C{i}_{n+1}\
& =2^{n}-1
\end{aligned}
\end{equation}\[故得:$F(n+1)=2F(n)+2^n-1$
代码就不写了
时间复杂度:$O(n)$
空间复杂度:$O(n)$
预计得分:60 points
\]
已经写出递推公式的话有两种思路:1. 数学方法推通项公式;2. 矩阵快速幂加速递推公式。
方法一:数学方法推通项公式:
\[\begin{equation}
\begin{aligned}
& F(n)=\sum_{i=1}^{n-1}C_n^{i+1}\cdot i\\
& =\sum_{i=1}^{n-1}{n!\over(i+1)!(n-i-1)!}\cdot i \\
& =\sum_{i=2}^n{n!\over i!(n-i)!} \cdot i+{n!\over i!(n-i)!}\\
& =\sum_{i=2}^n{n!\over(i-1)!(n-i)!}+C_n^i \\
\]& ={\sum_{i=2}n{C_n{i-1}}+(n-i+1)(2^n-n-1)\over n-i+1} \
& ={2{n-1}-n-2+(n-i+1)(2n-n-1)\over n-i+1}
\end{aligned}
\end{equation}\[\]
这里 \(2^{n-1}\) 用快速幂实现(注意,不能用 \(<<\) 来做,会爆 long long)
代码见code1
时间复杂度:\(O(\text{log}n)\)
空间复杂度:\(O(1)\)
预计得分:100 points
方法二:矩阵快速幂优化:
个人认为这个方法可能鲜有人能想到(太麻烦了),我就仔细讲一讲。
首先,观察递推公式中有如下几个影响值:\(F(n-1),2^{n-1},1\) ,故与单位矩阵相乘的矩阵为
\[\begin{bmatrix}
F(n-1)\\ 2^{n-1}\\ 1
\end{bmatrix}
\]得到的矩阵为
\[\begin{bmatrix}
F(n)\\ 2^{n}\\ 1
\end{bmatrix}
\]有递推式显然可得:
\[ \begin{cases}
F(n)=F(n-1)\times 2+2^{n-1}\times 1+1\times(-1)\\
2^n=F(n-1)\times0+2^{n-1}\times 2+1\times 0 \\
1=F(n-1)\times 0+2^{n-1}\times 0+1\times 1
\end{cases}
\](不会矩阵加速的可以做一做 P1939 【模板】矩阵加速(数列)和 P1962 斐波那契数列)
推出单位矩阵:
\[\begin{bmatrix}
2&1&-1\\ 0&2&0\\ 0&0&1
\end{bmatrix}
\]故矩阵递推式为:
\[\begin{bmatrix}
F(n-1)\\ 2^{n-1}\\ 1
\end{bmatrix}
\times
\begin{bmatrix}
2&1&-1\\ 0&2&0\\ 0&0&1
\end{bmatrix}
=
\begin{bmatrix}
F(n)\\ 2^{n}\\ 1
\end{bmatrix}
\]化为矩阵幂形式得:
\[\begin{bmatrix}
F(2)\\ 2^2\\ 1
\end{bmatrix}
\times
\begin{bmatrix}
2&1&-1\\ 0&2&0\\ 0&0&1
\end{bmatrix}^{n-2}
=
\begin{bmatrix}
F(n)\\ 2^{n}\\ 1
\end{bmatrix}
\]套魔板即可。
代码见code2
时间复杂度:\(O(\text{log}n)\)
空间复杂度:\(O(1)\)
两种方法的优劣:
- 第一种方法难算,需要较好的数学基础,但最后实现时时间复杂度在 \(O(1)\) — \(O(\text{log}n)\) ,常数极小。
 - 第二种方法是数列加速的常用方法,简单易想,但常数较大,本题为常数为27,即在大数据下比第一种方法慢2—3倍
 
Code1:
 #include<bits/stdc++.h>
  //#define file
  #define modn (int)(1e9+7)
  #define int long long
  using namespace std;
  int n;
  inline int ksm(int x,int y,int p)
  {
  	if(y==0) return 1%p;
  	if(y==1) return x%p;
  	int rst=ksm(x,y/2,p)%p;
  	if(y%2==0)
  	{
  		return rst*rst%p;
  	}else
  	{
  		int tmp=rst*rst%p;
  		return tmp*x%p;
  	}
  }
  signed main()
  {
  	#ifdef file
  	freopen("Agent1.in","r",stdin);
  	freopen("Agent1.out","w",stdout);
  	//F(n)=\sum_{i=1}^{n-1}C^(i+1)_n*i
  	//F(n)=F(n-1)*2+2^{n-1}-1
  	#endif
  	scanf("%lld",&n);
  	int ans=(n-2)*ksm(2,n-1,modn)%modn+1;
  	printf("%lld\n",ans);
  	return 0;
  }
Code2(本代码为我的教练所写,码风可能有些许不同):
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mod 1000000007
int jz[3][3] = {{2,1,-1},{0,2,0},{0,0,1}},
    jz1[3][3] = {{2,1,-1},{0,2,0},{0,0,1}};
int base[3][3];
void cheng()
{
    memset(base,0,sizeof(base));
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            for(int k=0;k<3;k++)
            {
                base[i][j] += jz1[i][k]*jz1[k][j];
                base[i][j] = (base[i][j]+mod)%mod;
            }
        }
    }
     memcpy(jz1,base,sizeof(base));
}
void chengjz()
{
    memset(base,0,sizeof(base));
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            for(int k=0;k<3;k++)
            {
                base[i][j] += jz1[i][k]*jz[k][j];
                base[i][j] = (base[i][j]+mod)%mod;
            }
        }
    }
    memcpy(jz1,base,sizeof(base));
}
void quickpow(int k)
{
    if(k==1) return;
    quickpow(k/2);
    cheng();
    if(k%2!=0) chengjz();
}
signed main()
{
    int n;
    cin>>n;
    if(n==2)
    {
        printf("1");
        return 0;
    }
    quickpow(n-2);
    int ans = (jz1[0][0]+ 4*jz1[0][1]%mod + mod + 1*jz1[0][2]) mod;
    cout<<ans;
    return 0;
}
												
											P4936 题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
		
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
 - noip2016十连测题解
		
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
 - BZOJ-2561-最小生成树 题解(最小割)
		
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
 - Codeforces Round #353 (Div. 2) ABCDE 题解 python
		
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
 - 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
		
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
 - 2016ACM青岛区域赛题解
		
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
 - poj1399 hoj1037 Direct Visibility 题解 (宽搜)
		
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
 - 网络流n题 题解
		
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
 - CF100965C题解..
		
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
 
随机推荐
- (转).NET Core中实现AOP编程
			
原文地址:https://www.cnblogs.com/xiandnc/p/10088159.html AOP全称Aspect Oriented Progarmming(面向切面编程),其实AOP对 ...
 - Golang slice和map的申明和初始化
			
1 前言 仅供记录使用. 2 代码 /** * @Author: FB * @Description: * @File: SliceMapInit.go * @Version: 1.0.0 * @Da ...
 - eclipse中启动tomcat后, 无法访问localhost:8080
			
问题: 今天老师讲了Servlet路径问题, 做了个测试在eclipse中启动tomcat后,在浏览器地址栏输入 http://localhost8080无法访问, 提示404错误, 正常情况是可以访 ...
 - 原油petrolaeum石油 Archaic spelling of petroleum
			
petrolaeum (uncountable) Archaic spelling of petroleum petroleum See also: Petroleum Contents [hide] ...
 - robotframework的学习笔记(十八)——RequestsLibrary库的API介绍
			
requestsLibrary的关键字不多,常用的就几个. Create Session: 创建一个session,连接某个服务器.Create Ntlm Session: 也是创建一个session ...
 - 使用Prometheus针对自己的服务器采集自定义的参数
			
用一个简单的例子来说明. 我用express和http搭了一个最简单的服务器,监听在8081端口上. 在metrics endpoint上,我会打印出这个服务器从启动至今,服务了多少次请求.这里我只是 ...
 - 应用在App Store上被拒重新提交审核流程指南
			
1. 打开地址: https://itunesconnect.apple.com 2. 输入APPID和密码后,再输入绑定手机后的验证码. 3. 查看“”我的APP“”,如果显示拒绝,可能需打开Mac ...
 - django数据表生成
			
在创建的app中models.py生成表结构 class 表名(models.Model): #表名一般首字母大写 中突出信息的大写 列名=models.Charfield(max_lenth=) # ...
 - Linux之RHEL7root密码破解(一)
			
很多时候我们都会有这样的经历,各种密码,各种复杂,忘记了怎么办???Windows的有关密码忘记了是可以通过相关的邮箱啊手机号等等是可以 找回的,那么Linux的root密码忘记了,该怎么办呢?那么接 ...
 - 使用Arduino开发板实现与MPU6050陀螺仪传感器连接的方法
			
MPU6050陀螺仪传感器具有许多强大的功能,采用单芯片封装.它是由一个MEMS加速度计.一个MEMS陀螺仪和温度传感器组成.该模块在将模拟量转换为数字量时非常准确,因为每个通道都有一个16位的模数转 ...