某种特殊的数列a1, a2, a3, ...的定义如下:a1 = 1, a2 = 2, ... , an = 2 * an − 1 + an - 2 (n > 2)。
给出任意一个正整数k,求该数列的第k项模以32767的结果是多少?
某种特殊的数列a1, a2, a3, ...的定义如下:a1 = 1, a2 = 2, ... , an = 2 * an − 1 + an - 2 (n > 2)。
给出任意一个正整数k,求该数列的第k项模以32767的结果是多少?
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数k (1 ≤ k < 1000000)。
n行,每行输出对应一个输入。输出应是一个非负整数。
2 1 8
1 408
//建表不一定非要建立整张表 //建立输入的最大值以内的表即可 //需要注意建表的过程直接用余数就可以,否则溢出 //余数的计算满足线性约束即可 #include<iostream> #include<vector> #include<map> using namespace std; int main() { long long num, m; cin >> num; map<long long, long long> table;//表的第一个数代表次序,第二个数代表余数 table[1] = 1; table[2] = 2; table[3] = 5; while (num--) { cin >> m; if (table[m] == 0) { for (long long i = 3; i <= m; i++) { if (table[i] == 0)//检查建表的时候是否建立过,如果建过直接跳 table[i] = (table[i - 1] * 2 + table[i - 2]) % 32767; } cout << table[m] << endl; } else cout << table[m] << endl; } return 0; }
res = [1, 2]
for i in range(int(input())):
k = int(input()) # 数列的第k项
while len(res) < k:
res.append(2 * res[-1] + res[-2])
print(res[k - 1] % 32767)
运行时间:910ms
可以将模运算
放在循环体中:
res = [1, 2]
for i in range(int(input())):
k = int(input()) # 数列的第k项
while len(res) < k:
res.append((2 * res[-1] + res[-2])% 32767)
print(res[k - 1] )
运行时间:367ms
import java.util.*; public class Main { private static final int MAX = 1000000 + 10; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] nums = new int[MAX]; nums[1] = 1; nums[2] = 2; for (int i=3; i<=MAX-5; i++) { nums[i] = (nums[i-1] * 2 + nums[i-2]) % 32767; } int T = sc.nextInt(); while (T-- != 0) { System.out.println(nums[sc.nextInt()]); } return; } }
//不得不提的是,看到这个求模递归类型的题,就想到可能会有个循环所以在此取巧 //事先编程处理(或者在程序内进行也可) //进行取模的大量输出,然后寻找到循环的部分(通过判断再次连续出现的1,2来看循环) //然后,复制粘贴,声明大数组。 //至于大数组的数量可以另外编一个很小的程序进行末端两位判断获取长度值。 //注意:这里把最末尾的循环数提到了数组零的位置,这样k直接取模就可以得到值 //另外,非取巧方法也有类似动态规划的思想,每一次都进行一个动态的存储(等等诸多细节) #include <iostream> using namespace std; int main() { int a[150] = {0, 1, 2, 5, 12, 29, 70, 169, 408, 985, 2378, 5741, 13860, 694, 15248, 31190, 12094, 22611, 24549, 6175, 4132, 14439, 243, 14925, 30093, 9577, 16480, 9770, 3253, 16276, 3038, 22352, 14975, 19535, 21278, 29324, 14392, 25341, 32307, 24421, 15615, 22884, 28616, 14582, 25013, 31841, 23161, 12629, 15652, 11166, 5217, 21600, 15650, 20133, 23149, 897, 24943, 18016, 28208, 8898, 13237, 2605, 18447, 6732, 31911, 5020, 9184, 23388, 23193, 4240, 31673, 2052, 3010, 8072, 19154, 13613, 13613, 8072, 29757, 2052, 1094, 4240, 9574, 23388, 23583, 5020, 856, 6732, 14320, 2605, 19530, 8898, 4559, 18016, 7824, 897, 9618, 20133, 17117, 21600, 27550, 11166, 17115, 12629, 9606, 31841, 7754, 14582, 4151, 22884, 17152, 24421, 460, 25341, 18375, 29324, 11489, 19535, 17792, 22352, 29729, 16276, 29514, 9770, 16287, 9577, 2674, 14925, 32524, 14439, 28635, 6175, 8218, 22611, 20673, 31190, 17519, 694, 18907, 5741, 30389, 985, 32359, 169, 32697, 29, 32755, 5, 32765, 1}; int n = 0; cin >> n; long int k = 0; for (int i = 0; i < n; i++) { cin >> k; cout << a[k % 150] << endl; } return 0; }
#include<bits/stdc++.h> using namespace std; int a[1000001]; int main(){ int n; scanf("%d",&n); for(int i = 1;i <= 1000000;i++){ if(i <= 2) a[i] = i; else a[i] = (2*a[i-1]+a[i-2])%32767; //在中间就应取模,防止溢出 } while(n--){ int k; scanf("%d",&k); printf("%d\n",a[k]); } return 0; } //由于数据范围明显,可以直接将每次计算的时间复杂度降为O(1)
#include <stdio.h> int main() { int n; int a[100000]; for(int i=0;i<100000;i++) { if(i<=2) a[i]=i; else a[i]=(2*a[i-1]+a[i-2])%32767; } while(scanf("%d",&n)!=EOF) { int k; for(int i=0;i<n;i++) { scanf("%d",&k); printf("%d\n",a[k]); } } return 0; }与其最后要模32767,不如给该数列提前模好
#include<iostream> using namespace std; int main(){ int n; int a[100000]; a[1]=1; a[2]=2; for(int i=3;i<100000;i++) a[i]=(2*a[i-1]+a[i-2])%32767; while(cin>>n){ int k; for(int i=0;i<n;i++){ cin>>k; cout<<a[k]<<endl; } } }
#include <stdio.h> int main() { long n; long arr[100000] = {1, 2}; //先生成数列,注意这里存入的是取模后的结果,否则数据会越界 for (int i = 2; i < 100000; i++) { arr[i] = (arr[i-1] * 2 + arr[i-2]) % 32767; } scanf("%d", &n);//获取测试用例个数 for (int i = 0; i < n; i++) { int num; scanf("%d", &num); printf("%ld\n", arr[num-1]);//循环打印每个测试用例的对应结果就行 } return 0; }
#include <iostream> using namespace std; int a[1000000]; int main() { int n; cin>>n; for(int i=1;i<1000000;i++) { if(i<=2) { a[i]=i; } else { a[i]=(2*a[i-1]+a[i-2])%32767; } } while(n--) { int k; cin>>k; cout<<a[k]<<endl; } }好坑这个题目,不要用递归,然后测试用例变态,提前在算的时候%23767,就不会溢出
#include <iostream> #include <vector> using namespace std; int main() { int n; int num; vector<long> arr(1000000); arr[0] = 1; arr[1] = 2; for (int i = 2; i < 1000000; ++i) { arr[i] = (2 * arr[i - 1] + arr[i - 2]) % 32767; //存进去后面再取出来 } cin >> n; while (n--) { cin >> num; cout << arr[num - 1] << endl; } return 0; }
var n = readline() var numArr = new Array(2) for(var j=0;j<n;j++){ var k = readline() numArr[0] = 1 numArr[1] = 2 for(var i=2;i<k;i++){ numArr[i] = (2*numArr[i-1] + numArr[i-2])%32767 } print(numArr[k-1]) }
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); int n= in.nextInt(); int [] arr = new int [n]; int max = 0; for(int i= 0;i< n;i++){ arr[i]= in.nextInt(); if(arr[i]>max){ max = arr[i]; } } int [] s= new int [max+1]; s[1]= 1;s[2]= 2; for(int i=3;i<max+1;i++){ //之前在输出的时候取模,case:0.0% //计算的时候取模,就提交成功了 //有没有大佬解释一下?????? s[i]= (s[i-1]*2 + s[i-2])%32767; } for(int i=0;i<n;i++){ System.out.println(s[arr[i]]); } } }
#include<iostream> using namespace std; int main(){ int n; int a[100000]; a[1]=1; a[2]=2; for(int i=3;i<100000;i++) a[i]=(2*a[i-1]+a[i-2])%32767; while(cin>>n){ int k; for(int i=0;i<n;i++){ cin>>k; cout<<a[k]<<endl; } } }稳妥的方法还是建表,用多少建多少。
def kItem(k): maxk = max(k) # 直接计算最大的k,避免了重复计算 if maxk < 3: return [1, 2] dp = [0]*maxk dp[0], dp[1] = 1, 2 for i in range(2, maxk): dp[i] = 2*dp[i-1] + dp[i-2] # 最简单直接的动态规划 return dp if __name__ == "__main__": n = int(input()) k = [] for i in range(n): k.append(int(input())) dpk = kItem(k) for j in k: print(dpk[j-1]%32767)