C++ 谁能降低我代码的复杂性呢。Codeforces Round113第2部分的问题E
问题的链接: 问题陈述: *给你一个四面体。让我们用字母A、B、C和D相应地标记它的顶点 一只蚂蚁站在四面体的顶点D上。蚂蚁很活跃,不会闲着。在每个时刻,他都会沿着四面体的某个边缘从一个顶点跨到另一个顶点。蚂蚁不能站在一个地方。 你不需要做很多事情来解决这个问题:你的任务是计算蚂蚁从初始顶点D到自身的方式的数量,精确到n步。换句话说,要求您找出从顶点D到自身长度为n的不同循环路径的数量。由于数字可能相当大,您应该以100000007(10^9)为单位打印它 + 7) * 输入: 第一行只包含整数n(1) ≤ N ≤ 107)-循环路径的所需长度 输出: 打印唯一的整数-所需的方式数,模为100000007(10e9 + 7) 示例:输入n=2,输出:3 输入n=4,输出:21 我解决问题的方法: 我已经编写了一个递归代码,它接受两个输入n和当前索引,然后我将遍历并探索所有可能的组合C++ 谁能降低我代码的复杂性呢。Codeforces Round113第2部分的问题E,c++,recursion,optimization,data-structures,dynamic-programming,C++,Recursion,Optimization,Data Structures,Dynamic Programming,问题的链接: 问题陈述: *给你一个四面体。让我们用字母A、B、C和D相应地标记它的顶点 一只蚂蚁站在四面体的顶点D上。蚂蚁很活跃,不会闲着。在每个时刻,他都会沿着四面体的某个边缘从一个顶点跨到另一个顶点。蚂蚁不能站在一个地方。 你不需要做很多事情来解决这个问题:你的任务是计算蚂蚁从初始顶点D到自身的方式的数量,精确到n步。换句话说,要求您找出从顶点D到自身长度为n的不同循环路径的数量。由于数字可能相当大,您应该以100000007(10^9)为单位打印它 + 7) * 输入: 第一行只包含整数
#include<iostream>
using namespace std;
#define mod 10000000
#define ll long long
ll count_moves=0;
ll count(ll n, int present)
{
if(n==0 and present==0) count_moves+=1, count_moves%=mod; //base_condition
else if(n>1){ //Generating All possible Combinations
count(n-1,(present+1)%4);
count(n-1,(present+2)%4);
count(n-1,(present+3)%4);
}
else if(n==1 and present) count(n-1,0);
}
int main()
{
ll n; cin>>n;
if(n==1) {
cout<<"0"; return;
}
count(n,0);
cout<<count_moves%mod;
}
#包括
使用名称空间std;
#定义模10000000
#定义ll long long
ll count_moves=0;
ll计数(ll n,整数当前)
{
如果(n==0和present==0)count\u moves+=1,count\u moves%=mod;//基本条件
else如果(n>1){//生成所有可能的组合
计数(n-1,(存在+1)%4);
计数(n-1,(存在+2)%4);
计数(n-1,(存在+3)%4);
}
如果(n==1且存在)计数(n-1,0);
}
int main()
{
ll n;cin>>n;
如果(n==1){
我相信你的问题之一是你在重新计算东西
以n=4为例,[0,3]中x的计数(3,x)被调用3次
但是,如果制作了一个std::map,则可以保存(n,present)对的值,并且只计算每个值一次
这将占用更多空间。完成后,地图将是4*(n-1)大。这可能仍然太大,无法容纳10^9
您可以做的另一件事是多线程。每个对count的调用都会引发它自己的线程。如果您决定使用它,那么在更改全局计数和std::map的状态时,您需要注意线程安全
编辑:
计算[1,n-1]中n的计数(n,x)一次,然后计算[0,3]中的计数[n,0]=a*计数(n-1,1)+b*计数(n-1,2)+c*计数(n-1,3)
如果你能找出a,b,c被赋予n的模式,或者甚至是n-1情况下的a,b,c的模式,那么你就可以很容易地解决这个问题。任何时候你构建了一个递归,并且超过了时间复杂度,你必须理解递归很可能就是问题所在
最好的解决方案是不使用递归
看看你得到的结果:
三,
六,
二十一,
六十
183
546
1641年
4920
⋮ ⋮
虽然可能很难找到前两个术语的模式,但以后会更容易
每个术语大约是上一个术语的3倍,或者更准确地说,
现在您可以为它编写一个for循环:
for(int i = 0; i < n-1; i++)
{
count_moves = count_moves * 3 + std::pow(-1, i) * 3;
}
此外,您甚至可以将其构建到通用术语公式中,以消除for循环:
或在代码中:
count_moves = (pow(3, n) + (n % 2 * 2 - 1) * -3) / 4;
但是,您无法摆脱pow()
这一次,否则您将不得不为此编写一个循环。代码没有编译,您正在对mod
进行去编译?您的计数函数也返回值,但您忽略了它。作为一个微观优化,您可以将%4
替换为&3
。%
操作通常涉及除法,这是非常昂贵的e、 编译器可能会识别模式并进行更改,具体取决于优化级别和编译器的功能。您肯定需要提高键入技能,以便不需要使用缩写宏。这些宏实际上会延长编译时间(因为它必须在编译之前执行所有这些替换,而不是解析已知关键字)。宏也使读取代码变得困难。我们查看ll
,然后确定它是您创建的类型还是宏。如果您使用long
,我们理解声明不会有问题。根据经验,超过了时间限制(TLE)错误,通常意味着您的实现或算法太慢,需要寻找更快的算法。优化不会提供足够的速度,请使用其他算法。
count_moves = (pow(3, n) + (n % 2 * 2 - 1) * -3) / 4;