Python 如何使用动态规划优化此代码

Python 如何使用动态规划优化此代码,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组成 输出: 对于每个

多拉特·拉姆是一位富有的商人。在停止使用货币后,这场突袭在他的住处进行,他的所有钱都被没收了。他非常渴望拿回自己的钱,他开始投资某些企业并从中获利。第一天,他的收入是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≤ 109

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);
}