数学 - 公式 V[i] = ([ V[i-1] * V[i-1] / (i + 2)] + V[ i-1] * i + i + 1) % 666013
Math - Formula V[i] = ([ V[i-1] * V[i-1] / (i + 2)] + V[ i-1] * i + i + 1) % 666013
我需要一些帮助来解决这个公式:
V[i] = ([ V[i-1] * V[i-1] / (i + 2)] + V[ i-1] * i + i + 1) % 666013
where v[0] = 3 and example: v[10000000] = 22230
我的解决方案是:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <fstream>
using namespace std;
ifstream fin ("smen.in");
ofstream fout ("smen.out");
unsigned long long int n, k;
int mod = 666013;
int numereus(int n)
{
if (n > 0)
{
k = numereus(n-1) % mod;
return ((((((((k*k)% mod)/((n%mod+2) % mod))%mod)+(k*(n%mod))% mod)% mod) + (n % mod)) % mod + 1) % mod;
}
else
{
return 3;
}
}
int main()
{
cin >> n;
cout << numereus(n);
return 0 ;
}
我的 C++ 解决方案不适用于大于 25000 的数字
递归解决方案最适合快速基本情况。
例如,对于每次递归,二分搜索都会去掉一半的解决方案 space,这样您就可以在大约 32 层递归中搜索 40 亿项。
处理 25,000 个项目的算法需要 25,000 个堆栈帧,因此可能更适合迭代解决方案。堆栈不是无限的资源。
在实现迭代解决方案方面,请参阅以下伪代码,它应该会给您一个想法:
def fn(n):
rv = 3
i = 0
while n > 0:
i = i + 1
rv = (rv * rv / (i + 2) + rv * i + i + 1) % 666013
n = n - 1
return rv
这是 Python 中的概念验证,它看起来与上面的代码非常相似,因为老实说,如果你抛弃所有 lambda/closure/list-comprehension 的东西,Python制作完美的伪代码语言:-)
def fn(n):
rv = 3
i = 0
while n > 0:
i = i + 1
rv = (rv * rv / (i + 2) + rv * i + i + 1) % 666013
n = n - 1
return rv
print fn(0)
print fn(1)
print fn(2)
print fn(10000000)
这输出:
3
8
35
22230
根据您的问题,最后一个似乎是 10,000,000
的正确值。
等效的 C++ 代码如下:
#include <iostream>
int numereus (int n) {
unsigned long long int rv = 3;
int i = 0;
while (n-- > 0) {
i = i + 1;
rv = (rv * rv / (i + 2) + rv * i + i + 1) % 666013;
}
return rv;
}
int main (void) {
std::cout
<< numereus(0) << '\n'
<< numereus(1) << '\n'
<< numereus(2) << '\n'
<< numereus(10000000) << '\n';
return 0 ;
}
保留现有代码的一种廉价方法是使用 memoization。您的代码很容易在循环中编写,在这种情况下,这可能应该是您的首选方法,但了解记忆是件好事。
这个想法是将昂贵的计算结果存储在缓存中,然后检索它们以节省时间(或资源)。
对于您的代码,每次调用 numereus
时,它都会将答案存储在一个数组中。如果稍后使用相同的参数调用 numereus
,它会检查数组中是否有答案,如果有,returns 不进行进一步的递归或计算就得到答案。
为了回答你的问题,我们可以用更大的值重复调用 numereus
来建立缓存。这防止了堆栈溢出的可能性并且仍然在 O(N)
时间内工作,因为对 numereus(i)
的每次调用都能够获取 numereus(i-1)
.
的缓存值
当然,构建这么大的缓存会消耗大量内存。处理这个问题的一种方法是只缓存每个 xth 值。例如,您可以只缓存偶数的输入。这将您需要的存储量减半 space,同时将递归深度加倍。
对于您的问题,以下未经测试的代码可能有效:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin ("smen.in");
ofstream fout ("smen.out");
unsigned long long int n, k;
int mod = 666013;
int numereus(std::vector<int> &memoized, int n){
if(memoized[n]!=-1)
return memoized[n];
if (n > 0){
k = numereus(memoized,n-1) % mod;
return memoized[n]=((((((((k*k)% mod)/((n%mod+2) % mod))%mod)+(k*(n%mod))% mod)% mod) + (n % mod)) % mod + 1) % mod;
} else {
return 3;
}
}
int main()
{
std::vector<int> memoized(10000000);
//I use -1 as a place holder here. Just make sure this is a value your function can never produce
std::fill(memoized.begin(),memoized.end(),-1);
cin >> n;
for(int i=0;i<n;i++) //Build table of answers
numereus(memoized,i);
cout << numereus(memoized,n);
return 0 ;
}
我需要一些帮助来解决这个公式:
V[i] = ([ V[i-1] * V[i-1] / (i + 2)] + V[ i-1] * i + i + 1) % 666013 where v[0] = 3 and example: v[10000000] = 22230
我的解决方案是:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <fstream>
using namespace std;
ifstream fin ("smen.in");
ofstream fout ("smen.out");
unsigned long long int n, k;
int mod = 666013;
int numereus(int n)
{
if (n > 0)
{
k = numereus(n-1) % mod;
return ((((((((k*k)% mod)/((n%mod+2) % mod))%mod)+(k*(n%mod))% mod)% mod) + (n % mod)) % mod + 1) % mod;
}
else
{
return 3;
}
}
int main()
{
cin >> n;
cout << numereus(n);
return 0 ;
}
我的 C++ 解决方案不适用于大于 25000 的数字
递归解决方案最适合快速基本情况。
例如,对于每次递归,二分搜索都会去掉一半的解决方案 space,这样您就可以在大约 32 层递归中搜索 40 亿项。
处理 25,000 个项目的算法需要 25,000 个堆栈帧,因此可能更适合迭代解决方案。堆栈不是无限的资源。
在实现迭代解决方案方面,请参阅以下伪代码,它应该会给您一个想法:
def fn(n):
rv = 3
i = 0
while n > 0:
i = i + 1
rv = (rv * rv / (i + 2) + rv * i + i + 1) % 666013
n = n - 1
return rv
这是 Python 中的概念验证,它看起来与上面的代码非常相似,因为老实说,如果你抛弃所有 lambda/closure/list-comprehension 的东西,Python制作完美的伪代码语言:-)
def fn(n):
rv = 3
i = 0
while n > 0:
i = i + 1
rv = (rv * rv / (i + 2) + rv * i + i + 1) % 666013
n = n - 1
return rv
print fn(0)
print fn(1)
print fn(2)
print fn(10000000)
这输出:
3
8
35
22230
根据您的问题,最后一个似乎是 10,000,000
的正确值。
等效的 C++ 代码如下:
#include <iostream>
int numereus (int n) {
unsigned long long int rv = 3;
int i = 0;
while (n-- > 0) {
i = i + 1;
rv = (rv * rv / (i + 2) + rv * i + i + 1) % 666013;
}
return rv;
}
int main (void) {
std::cout
<< numereus(0) << '\n'
<< numereus(1) << '\n'
<< numereus(2) << '\n'
<< numereus(10000000) << '\n';
return 0 ;
}
保留现有代码的一种廉价方法是使用 memoization。您的代码很容易在循环中编写,在这种情况下,这可能应该是您的首选方法,但了解记忆是件好事。
这个想法是将昂贵的计算结果存储在缓存中,然后检索它们以节省时间(或资源)。
对于您的代码,每次调用 numereus
时,它都会将答案存储在一个数组中。如果稍后使用相同的参数调用 numereus
,它会检查数组中是否有答案,如果有,returns 不进行进一步的递归或计算就得到答案。
为了回答你的问题,我们可以用更大的值重复调用 numereus
来建立缓存。这防止了堆栈溢出的可能性并且仍然在 O(N)
时间内工作,因为对 numereus(i)
的每次调用都能够获取 numereus(i-1)
.
当然,构建这么大的缓存会消耗大量内存。处理这个问题的一种方法是只缓存每个 xth 值。例如,您可以只缓存偶数的输入。这将您需要的存储量减半 space,同时将递归深度加倍。
对于您的问题,以下未经测试的代码可能有效:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin ("smen.in");
ofstream fout ("smen.out");
unsigned long long int n, k;
int mod = 666013;
int numereus(std::vector<int> &memoized, int n){
if(memoized[n]!=-1)
return memoized[n];
if (n > 0){
k = numereus(memoized,n-1) % mod;
return memoized[n]=((((((((k*k)% mod)/((n%mod+2) % mod))%mod)+(k*(n%mod))% mod)% mod) + (n % mod)) % mod + 1) % mod;
} else {
return 3;
}
}
int main()
{
std::vector<int> memoized(10000000);
//I use -1 as a place holder here. Just make sure this is a value your function can never produce
std::fill(memoized.begin(),memoized.end(),-1);
cin >> n;
for(int i=0;i<n;i++) //Build table of answers
numereus(memoized,i);
cout << numereus(memoized,n);
return 0 ;
}