在你面前有一个n阶的楼梯,你一步只能上1阶或2阶。
请问计算出你可以采用多少种不同的方式爬完这个楼梯。
#include <iostream> #include <string> using namespace std; string BigData(string s1, string s2){ string res = ""; int i = s1.size() - 1; int j = s2.size() - 1; int carry = 0; //进位 while (i >= 0 || j >= 0){ // s2一定大于s1(斐波那契数列的后者 > 前者) if(i < 0){ //当小的字符串先走完时,就剩大字符串了,同理进行逐位添加 res = to_string((s2[j] - '0') + carry) + res; carry = 0; //只剩一个字符串就不存在进位了,因为都是个位数 } else{ //从后往前进行逐位相加,如123+567,从3+7开始往前加,别忘了加上进位 int tmp = (s1[i] - '0') + (s2[j] - '0') + carry; carry = tmp / 10; //得到进位 tmp = tmp % 10; //得到余数 res = to_string(tmp) + res; //这里顺序记得不能颠倒,不然就错了 } --i; --j; } //为什么下面还要判定呢?因为比如3+7应该等于10,但是 //上面的计算出的res只有0(余数),所以这里要考虑周全 if(carry == 1) res = '1' + res; return res; } int main(){ int n; cin >> n; //斐波那契 if(n == 1){ cout << 1 << endl; return 0; } else if(n == 2){ cout << 2 << endl; return 0; } string i = "1"; string j = "2"; string ans = ""; for(int k = 1; k <= n - 2; ++k){ ans = BigData(i, j); // i + j i = j; j = ans; } cout << ans << endl; return 0; }
递推公式很简单,f(n)=f(n-1)+f(n-2),f(1)=1,f(2)=2. 值得注意的是本题还有大整数问题,所以使用转化为字符串形式,额外写一个大整数相加函数 #include<iostream> using namespace std; //大整数相加函数 string add(string a,string b) { int i=a.size()-1; int j=b.size()-1; string res=""; int carry=0; while(i>=0&&j>=0) { char tmp; int num; num=(a[i]-48)+(b[j]-48)+carry; carry=num/10; num=num%10; tmp=char(num+48); res=tmp+res; i--; j--; } while(i>=0) { char tmp; int num; num=(a[i]-48)+carry; carry=num/10; num=num%10; tmp=char(num+48); res=tmp+res; i--; } while(j>=0) { char tmp; int num; num=(b[j]-48)+carry; carry=num/10; num=num%10; tmp=char(num+48); res=tmp+res; j--; } if(carry>0) { res=char(carry+48)+res; } return res; } int main() { int n; cin>>n; string a[n+1]; for(int i=0;i<n+1;i++) { a[i]='0'; } a[0]='1'; a[1]='1'; for(int i=2;i<n+1;i++) { a[i]=add(a[i-1],a[i-2]); } cout<<a[n]; }
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; int num[103][30] = {0}; num[1][29] = 1;//第一项 num[2][29] = 2;//第二项 for (int i = 3; i <= n; i++) { for (int j = 29; j >= 0; j--)//循环,数组行是从1开始,列是从0开始 { if ((num[i - 1][j] + num[i - 2][j]+num[i][j]) >= 10)//进位,占多一个元素 num[i][j - 1] += 1; num[i][j] = (num[i - 1][j] + num[i - 2][j] + num[i][j]) % 10; } } int j = 0; while (num[n][j] == 0) j++; for (int i = j; i < 30; i++) cout << num[n][i]; return 0; }
import sys def diffroad(n): res =[1,2] if n<3: return res[n-1] for i in range(3,n+1): res[(i-1)%2] += res[i%2] return res[(i-1)%2] if __name__=="__main__": n = int(sys.stdin.readline().strip()) print(diffroad(n))
import java.util.*; import java.math.*; public class Main{ static BigInteger func(int n){ if(n==0) return new BigInteger("0"); if(n==1) return new BigInteger("1"); BigInteger[] ll=new BigInteger[n]; ll[0]=new BigInteger("1"); ll[1]=new BigInteger("2"); for(int i=2;i<n;i++){ ll[i]=ll[i-1].add(ll[i-2]); } return ll[n-1]; } public static void main(String[] args){ Scanner sc=new Scanner(System.in); int n=sc.nextInt(); System.out.println(func(n)); } }
#include <bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; int a[101][30] = {0}; a[1][29] = 1; a[2][29] = 2; for(int i=3;i<=n;i++) for(int j=29;j>=0;j--){ int t = a[i-1][j]+a[i-2][j]+a[i][j]; if(t >= 10) a[i][j-1] += 1; a[i][j] = t%10; } bool zero = true; for(int j=0;j<30;j++){ if(zero && a[n][j]!=0) zero = false; if(!zero) cout<<a[n][j]; } cout<<endl; return 0; }
考察斐波那契数列
题目要求:只能跳1阶或者2阶。
定义阶有
种跳法
初次提交这个题会发现通过率只有 50%,是因为没有考虑到整数溢出的问题,用BigInteger处理就Ok了。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigInteger; public class Main { public static void main(String[] args) throws IOException { BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(bf.readLine()); if (n < 3) { System.out.println(n); return; } BigInteger one = BigInteger.valueOf(1); BigInteger two = BigInteger.valueOf(2); BigInteger ret = BigInteger.valueOf(0); for (int i = 3; i <= n; i++) { ret = one.add(two); one = two; two = ret; } System.out.println(ret); } }
#include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; vector<vector<int>> dp(n + 5, vector<int> (100, 0)); dp[1][0] = 1; dp[2][0] = 2; int len = 1; for (int i = 3; i <= n; i++) { for (int j = 0; j < len; j++) { dp[i][j] += dp[i - 1][j] + dp[i - 2][j]; if (dp[i][j] > 9) { dp[i][j + 1] += dp[i][j] / 10; dp[i][j] %= 10; len += (j == len - 1); } } } for (int i = 0; i < len; i++) cout << dp[n][len - i - 1]; cout << endl; return 0; }
import java.math.BigInteger; import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); ArrayList<BigInteger> list = new ArrayList<>(); for (int i = 1; i <= n; i++) { BigInteger temp = (i <= 2) ? BigInteger.valueOf(i) : list.get(i - 2).add(list.get(i - 3)); list.add(temp); } System.out.println(list.get(list.size() - 1)); } }
const rl = require("readline").createInterface({ input: process.stdin }); var iter = rl[Symbol.asyncIterator](); const readline = async () => (await iter.next()).value; void async function () { // Write your code here while(line = await readline()){ let num = parseInt(line) if(num == 0) { console.log(1) return } if(num == 1) { console.log(1) return } let prev1 = BigInt(1),prev2 = BigInt(1) let total = 0 for(let i = 1;i < num;i++) { total = (prev1 + prev2).toString() prev2 = prev1 prev1 = BigInt(total) } console.log(total) } }()
const rl = require("readline").createInterface({ input: process.stdin }); var iter = rl[Symbol.asyncIterator](); const readline = async () => (await iter.next()).value; void async function () { // Write your code here while(line = await readline()){ let num = Number(line) let dp = new Array(num+1).fill(0) dp[1] = 1 dp[2] = 2 for(let i = 3; i <= num; i++) { dp[i] = dp[i-1] + dp[i-2] } console.log(dp[num]) } }()但是这道题,必须得考虑大数相加
const rl = require("readline").createInterface({ input: process.stdin }); var iter = rl[Symbol.asyncIterator](); const readline = async () => (await iter.next()).value; void async function () { // Write your code here while(line = await readline()){ let num = Number(line) let dp = new Array(num+1).fill(0) dp[1] = 1 dp[2] = 2 for(let i = 3; i <= num; i++) { dp[i] = numAdd(dp[i-1].toString(), dp[i-2].toString()) } console.log(dp[num]) } /** * 这个函数是用来进行大数相加的,可以反复阅读一下 */ function numAdd(first, second) { // 取两个数字的最大长度 let maxLength = Math.max(first.length, second.length); // 用 0 去补齐长度 first = first.padStart(maxLength , 0); second = second.padStart(maxLength , 0); // 定义加法过程中需要用到的变量 let temp = 0; let carry = 0; // "进位" let sum = ""; for(let i = maxLength-1; i >= 0; i--){ temp = parseInt(first[i]) + parseInt(second[i]) + carry; carry = Math.floor(temp / 10); sum = temp % 10 + sum; } if(carry == 1){ sum = "1" + sum; } return sum; } }()
import java.math.BigDecimal; import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int sum = in.nextInt(); if (sum == 1) { System.out.println(1); return; } else if (sum == 2) { System.out.println(2); return; } else if (sum <= 0) { System.out.println(); return; } BigDecimal[] ary = new BigDecimal[sum]; ary[0] = BigDecimal.valueOf(1); ary[1] = BigDecimal.valueOf(2); for (int i = 2; i < sum; i++) { ary[i] = ary[i - 2].add(ary[i - 1]); } System.out.println(ary[sum - 1].toString()); } }
#include <bits/stdc++.h> using namespace std; string strAdd(string a, string b) { int level = 0; reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); int aIndex = 0; int bIndex = 0; string res = ""; while (aIndex < a.size() || bIndex < b.size() || level != 0) { int val = (aIndex < a.size() ? a[aIndex++] - '0' : 0) + (bIndex < b.size() ? b[bIndex++] - '0' : 0) + level; level = val / 10; res += to_string(val % 10); } reverse(res.begin(), res.end()); return res; } int main() { int n; cin >> n; vector<string> dp(101, "0"); dp[1] = "1"; dp[2] = "2"; for (int i = 3; i < 101; i++) { dp[i] = strAdd(dp[i - 1], dp[i - 2]); } cout << dp[n] << endl; return 0; }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String[] dp = new String[101]; // 楼梯的台阶数小于等于100 dp[1] = String.valueOf(1); dp[2] = String.valueOf(2); for (int i = 3; i <= 100; i++) { dp[i] = add(dp[i - 1], dp[i - 2]); // 两个字符串相加 } int n = sc.nextInt(); System.out.println(dp[n]); } public static String add(String s1, String s2) { int n1 = s1.length() - 1; int n2 = s2.length() - 1; int add = 0; // 记录进位 StringBuffer sb = new StringBuffer(); // 存放结果 while (n1 >= 0 || n2 >= 0) { int x = (n1 >= 0) ? s1.charAt(n1) - '0' : 0; int y = (n2 >= 0) ? s2.charAt(n2) - '0' : 0; int sum = x + y + add; if (sum > 9) { sb.insert(0, sum % 10); add = 1; } else { sb.insert(0, sum); add = 0; } n1--; n2--; } if (add == 1) sb.insert(0, 1); // 最后查看是否有进位 return sb.toString(); } }