Python 如何使用动态规划优化此代码
多拉特·拉姆是一位富有的商人。在停止使用货币后,这场突袭在他的住处进行,他的所有钱都被没收了。他非常渴望拿回自己的钱,他开始投资某些企业并从中获利。第一天,他的收入是X卢比,第二天是Y卢比。Daulat Ram观察了他的成长情况,并想计算第n天的收入 他发现的函数是FN=FN-1+FN-2+FN-1×FN-2 考虑到他第0天和第1天的收入,计算他第n天的收入是的,就这么简单 输入: 第一行输入由一个表示测试用例数量的整数T组成 接下来的每一条T线分别由三个整数F0、F1和N组成 输出: 对于每个测试用例,打印一个整数FN,因为输出可能很大,所以计算答案模109+7 限制条件: 一,≤ T≤ 105 0≤ F0,F1,N≤ 109Python 如何使用动态规划优化此代码,python,python-3.x,recursion,optimization,dynamic-programming,Python,Python 3.x,Recursion,Optimization,Dynamic Programming,多拉特·拉姆是一位富有的商人。在停止使用货币后,这场突袭在他的住处进行,他的所有钱都被没收了。他非常渴望拿回自己的钱,他开始投资某些企业并从中获利。第一天,他的收入是X卢比,第二天是Y卢比。Daulat Ram观察了他的成长情况,并想计算第n天的收入 他发现的函数是FN=FN-1+FN-2+FN-1×FN-2 考虑到他第0天和第1天的收入,计算他第n天的收入是的,就这么简单 输入: 第一行输入由一个表示测试用例数量的整数T组成 接下来的每一条T线分别由三个整数F0、F1和N组成 输出: 对于每个
def function(x1):
if x1==2: return fnc__1+fnc__0*fnc__1+fnc__0
elif x1==1: return fnc__1
elif x1==0: return fnc__0
return function(x1-1)+function(x1-2)*function(x1-1)+function(x1-2)
for i in range(int(input())): #input() is the no of test cases
rwINput = input().split()
fnc__0 =int(rwINput[0])
fnc__1 = int(rwINput[1])
print(function(int(rwINput[2])))
一种简单的优化方法是缓存函数的结果。python提供了一种仅使用hat的机制。您需要做的就是用以下内容装饰您的功能:
from functools import lru_cache
@lru_cache()
def function(n, F0=1, F1=2):
if n == 0:
return F0
elif n == 1:
return F1
else:
f1 = function(n-1, F0, F1)
f2 = function(n-2, F0, F1)
return f1+f2 + f1*f2
您可以根据需要稍微调整lru_缓存。它与python垃圾收集器配合得非常好,因为它只将WeakRefs存储到对象中
测试用例:
for i in range(7):
print('{}: {:7d}'.format(i, function(i)))
印刷品:
0: 1
1: 2
2: 5
3: 17
4: 107
5: 1943
6: 209951
若要获得以整数为模的答案,但不清楚问题中的模,可以执行以下操作:
MOD = 10**9 + 7 # ???
@lru_cache()
def function(n, F0=1, F1=2):
if n == 0:
return F0
elif n == 1:
return F1
else:
f1 = function(n-1, F0, F1)
f2 = function(n-2, F0, F1)
return (f1+f2 + f1*f2) % MOD
您只需开始执行该函数并将f1分配给f0,将结果分配给f1即可。对这n次进行迭代,所需结果为f0: 输入:
8
1 2 0
1 2 1
1 2 2
1 2 3
1 2 4
1 2 5
1 2 6
10 13 100
输出:
1
2
5
17
107
1943
209951
276644752
有人给了我这个答案,它起了作用,但我不知道怎么做
#include <stdio.h>
#include <stdlib.h>
#define mod 1000000007
long long int power(long long int,long long int);
void mult(long long int[2][2],long long int[2][2]);
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
int n;
int pp,p;
scanf("%d%d%d",&pp,&p,&n);
long long int A[2][2] = {{1,1},{1,0}};
n = n-1;
long long int B[2][2] = {{1,0},{0,1}};
while(n>0)
{
if(n%2==1)
mult(B,A);
n = n/2;
mult(A,A);
}
long long int result = ((power(pp+1,B[0][1])*power(p+1,B[0][0]))%mod - 1 + mod)%mod;
printf("%lld\n",result);
}
}
long long int power(long long int a,long long int b)
{
long long int result = 1;
while(b>0)
{
if(b%2==1)
result = (result*a)%mod;
a = (a*a)%mod;
b = b/2;
}
return result;
}
void mult(long long int A[2][2],long long int B[2][2])
{
long long int C[2][2];
C[0][0] = A[0][0]*B[0][0] + A[0][1]*B[1][0];
C[0][1] = A[0][0]*B[0][1] + A[0][1]*B[1][1];
C[1][0] = A[1][0]*B[0][0] + A[1][1]*B[1][0];
C[1][1] = A[1][0]*B[0][1] + A[1][1]*B[1][1];
A[0][0] = C[0][0]%(mod-1);
A[0][1] = C[0][1]%(mod-1);
A[1][0] = C[1][0]%(mod-1);
A[1][1] = C[1][1]%(mod-1);
}
我知道这篇文章很老,但我想指出一个重要的问题已经被回避了:函数很快就会得到巨大的值,并且只需要一个模。和或积的模可以用模的和或积来计算。所以要得到一个大N的正确答案,唯一的方法是存储模,而不是Fn
以下是我对如何使用动态规划的看法。动态编程只是缓存结果,以避免重新计算递归树的所有分支。存储连续的Fn是所需的一切。如果该算法只需要使用一次,您甚至不必将整个数组存储在这里:计算f0和f1,并将最后两个计算值与模一起保留,以通过简单循环找到结果。如果算法运行多次,但结果仍未计算,您只需检索最后两个计算值,一个用于存储最后一个计算值索引的变量将非常有用,以便从那里重新启动。@hiroprotation:实际上,记忆可以是一种简单廉价的动态编程形式。@WillemVanOnsem:哦,对了。谢谢你的澄清!它不起作用。例如,尝试1 2 4期望输出为117,但这样做会得到11。说明:F0=1 F1=2 F2=1+2+1×2=5 F3=2+5+2×5=17 F4=5+17+5×17=107@ShailabSingh:更新。您没有为递归提供起始条件。现在F0=1,F1=2,一切都好了。@Shailabsing:你能更精确一点吗?什么时候开始出错?它怎么不起作用?您将结果与什么进行比较?@Shailabsing您能将完整的问题陈述添加到问题中吗?很多时候,网站会要求你给出一些大数值的模值,这可能会解释输入量大的问题。现在这会重现你的结果吗?或者你的问题中有什么我遗漏的?超过了时间限制!顺便说一句,不要问我输入,只要看看限制@Shailabsing根据您对问题的编辑更新了答案。由于数字的大小并没有受到任何限制,所以预期之前的答案会超过时间限制。虽然Python整数没有任何限制,但运算速度非常慢。我假设模109+7实际上是指10**9+7,因为它通常用于此类问题,所以再次超出了时间限制!!PS:错误的值可能是由于溢出值太大,因为模只在末尾计算。他一定花了相当长的时间分析问题,以找到一个解析解,该解析解是根据两个输入数和一个仅依赖于循环中计算的n的矩阵。函数mult是矩阵乘法a:=a*B[模mod-1]。
#include <stdio.h>
#include <stdlib.h>
#define mod 1000000007
long long int power(long long int,long long int);
void mult(long long int[2][2],long long int[2][2]);
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
int n;
int pp,p;
scanf("%d%d%d",&pp,&p,&n);
long long int A[2][2] = {{1,1},{1,0}};
n = n-1;
long long int B[2][2] = {{1,0},{0,1}};
while(n>0)
{
if(n%2==1)
mult(B,A);
n = n/2;
mult(A,A);
}
long long int result = ((power(pp+1,B[0][1])*power(p+1,B[0][0]))%mod - 1 + mod)%mod;
printf("%lld\n",result);
}
}
long long int power(long long int a,long long int b)
{
long long int result = 1;
while(b>0)
{
if(b%2==1)
result = (result*a)%mod;
a = (a*a)%mod;
b = b/2;
}
return result;
}
void mult(long long int A[2][2],long long int B[2][2])
{
long long int C[2][2];
C[0][0] = A[0][0]*B[0][0] + A[0][1]*B[1][0];
C[0][1] = A[0][0]*B[0][1] + A[0][1]*B[1][1];
C[1][0] = A[1][0]*B[0][0] + A[1][1]*B[1][0];
C[1][1] = A[1][0]*B[0][1] + A[1][1]*B[1][1];
A[0][0] = C[0][0]%(mod-1);
A[0][1] = C[0][1]%(mod-1);
A[1][0] = C[1][0]%(mod-1);
A[1][1] = C[1][1]%(mod-1);
}