Problem Set 1
Problem Set 1.1
Problem 1.1.1
基本情况:若
归纳假设:令
归纳步骤:若
- 若
为偶数,则返回 ,由于函数的第二个参数变小了,根据数学归纳法,有 ,返回正确值 - 若
为奇数,则返回 ,由于函数的第二个参数变小了,根据数学归纳法,有 ,返回正确值
基本情况:若
归纳假设:令
归纳步骤:若
Problem 1.1.2
由代码有
Problem 1.1.3
令
可知算法会选择会选择
使用深度优先搜索,考察
void work(int step,int cnt)
//step表示当前正在选择第step个集合
//cnt表示已经选择的集合个数
{
if(step==m+1)
{
//now表示选择了的集合的并集
//ans表示最小覆盖数
if(now.size()==n) ans=min(ans,cnt);
return;
}
work(step+1,cnt);
set<int> now_copy=now;
for(set<int>::iterator it=s[step].begin();it!=s[step].end();++it)
now.insert(*it);
work(step+1,cnt+1);
now=now_copy;
}
能,除非问题无解,比如令
Problem 1.1.4
以下代码均忽略数值溢出的问题
int work(int T)//设S是全局变量,找到了返回最后一个被扫描到的硬币的下标,未找到返回0
{
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=s[i];
if(sum==T) return i;
}
return 0;
}
反例:
int work(int T)//设S是全局变量,找到了返回最后一个被扫描到的硬币的下标,未找到返回0
{
sort(s+1,s+n+1);
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=s[i];
if(sum==T) return i;
}
return 0;
}
反例同
int work(int T)//设S是全局变量,找到了返回最后一个被扫描到的硬币的下标,未找到返回0
{
sort(s+1,s+n+1,greater<int>());
int sum=0;
for(int i=1;i<=n;i++)
{
sum+=s[i];
if(sum==T) return i;
}
return 0;
}
反例同
Problem Set 1.2
Problem 1.2.1
利用数学归纳法证明。
基本情况:有
归纳假设:设对前
归纳步骤:由于
利用数学归纳法证明。
基本情况:对于
归纳假设:假设对于前
归纳步骤:要证明
证毕
Problem 1.2.2
直接证明
在二叉树中,有边数
而边数又等于子节点个数,所以子节点个数等于总结点个数
在这道题目中,即
化简即
Problem 1.2.3
我认为题干的符号可能使用的不是很正确,像
- O:若
,则存在 使得当 时, 。若 ,则存在 使得当 时, 。取 ,当 时, ,即 - Ω:类似 O,方向相反
- Θ:结合 O 和 Ω 的传递性,存在常数使得上下界同时传递
- o:若
,则 。若 ,则 。故 ,即 - ω:类似 o,极限趋向于无穷大,乘积仍趋向无穷大
- O:取
,则 ,故 - Ω:同理,
,故 - Θ:由 O 和 Ω 自反性,得
- 自反性:已证
- 对称性:若
,则存在 使得 ,从而 ,即 - 传递性:已证
综上,Θ 是等价关系
- O与Ω:
- o与ω:
- o(g) ∩ ω(g) = ∅:若
,则 ,但若 ,则 ,矛盾 - Θ(g) ∩ o(g) = ∅:若
,则 使得 ,但 要求 对所有 ,矛盾 - Θ(g) ∩ ω(g) = ∅:类似上一条
Problem 1.2.4
下面的小于符号和等于符号都代表渐进复杂度
直接做
Problem Set 1.3
Problem 1.3.1
第二个是正确的。对
假设对前
第一个是不正确的,类似上面的正面,有
Problem 1.3.2
a.
有
b.
c.
有
d.
有
e.
f.
用递归树进行计算,如下
可以知道每一层的计算量都为
g.
利用递归树分析。对于第一层,总耗费为
也可以用代入法做,而且得出的结论更强。
假设
Problem 1.3.3
仍然使用递归树分析,将
另外一种做法:
继续展开可以得到类似结论
Problem 1.3.4
(a)
最终的矩阵一共有四个元素,每个元素都是经过两次乘法运算和一次加法运算得到的,所以一共会经过八次乘法运算和四次加法运算;根据递推,不难得到,如果不使用矩阵快速幂而是使用
(b)
这个使用矩阵快速幂即可,数学原理是矩阵乘法满足结合律,代码见下
void mul(arr x,arr y)
{
ll z[1][2];
memset(z,0,sizeof(z));
for(int i=0;i<=0;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
z[i][j]=(z[i][j]+x[i][k]*y[k][j])%p;
memcpy(x,z,sizeof(z));
}
void mulself(arr x,arr y)
{
ll z[2][2];
memset(z,0,sizeof(z));
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=1;k++)
z[i][j]=(z[i][j]+x[i][k]*y[k][j])%p;
memcpy(x,z,sizeof(z));
}
int main()
{
n=read();
ans[0][0]=0,ans[0][1]=1;
ll A[2][2]={{0,1},{1,1}};
while(n)
{
if(n&1) mul(ans,A);
mulself(A,A);
n>>=1;
}
printf("%lld\n",ans[0][0]);
return 0;
}
(c)
要计算中间结果都是
(d)
我们已经证明了会有
(e)
由提示,我们真正的复杂度其实是
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构