这几天一直在做题,没有抽出时间来写总结..HDU的Steps做到了第六节了,温习的一些知识点,也学到了不少新东西..加油,争取在省赛前能尽量多学一些!!
STEPS 2.3的题目基本都是递推或者大数,当然这两者常常是结合在一起的,因为递推尤其像卡特兰数之类的,很容易得到一个非常大的数值,一般简单的只有加法的用CPP就可以了,懒的去启慢吞吞的Eclipse..当然了,复杂的大数运算还是用JAVA比较好一些,毕竟容易写,也不会出错..
2.3.1 HDU1002 A+BⅡ入门大数
主要代码
for(int i=0;i<l1;i++)i1[i]=s1[l1-i-1]-'0'; for(int i=0;i<l2;i++)i2[i]=s2[l2-i-1]-'0'; for(int i=0;g!=0||i<l1||i<l2;i++){ ans[i]=(i1[i]+i2[i]+g)%10; g=(i1[i]+i2[i]+g)/10; l3++; }
2.3.2 HDU1063 Exponentiation 高精度幂运算
Java水过,不过要注意几个方法的调用,去掉末尾和开头0,并且转成字符串显示,否则会用默认的科学计数法显示
import java.math.BigDecimal; import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String[] args) { new Main(); } public Main(){ BigDecimal r; int n; Scanner sc=new Scanner(System.in); while(sc.hasNext()){ r=sc.nextBigDecimal(); n=sc.nextInt(); //去末尾0,转成字符串 String st=r.pow(n).stripTrailingZeros().toPlainString(); int ind=0; while(true){ if(st.charAt(ind)!='0')break; ind++; } st=st.substring(ind); System.out.println(st); } } }
2.3.3 HDU1018 Big Number 求N!位数
一个数的位数可以用Log(N)+1得出(底为10),证明很简单,N可以写成a*10^n,a为小于10的实数,而N的位数就是n+1
f(N!)=Log(N!)+1=Log(N)+log(N-1)+...Log(1)+1
#include <cstdio> #include <cmath> using namespace std; /* F(N)=log(N)/log(10)+1 数与位数的关系 F(N!)=(log(N)+log(N-1)+...+log(1))/log(10)+1 */ int solve(int n){ double r=0; for(int i=1;i<=n;i++)r+=log(i); return (int)(r/log(10))+1; } int main(){ int cas,n; scanf("%d",&cas); while(cas--){ scanf("%d",&n); printf("%d\n",solve(n)); } }
树的个数=左树的总数*右树的总数,即d[n]=d[0]d[n-1]+d[1]d[n-2]+....+d[n-1][0]
卡特兰数,Java水过,可以求出公式.我没有求,直接用递归写的.跟记忆化搜索的思想有些类似
import java.math.BigDecimal; import java.math.BigInteger; import java.util.Scanner; public class Tes { public static void main(String[] args) { new Tes(); } //d[n]=d[0]d[n-1]+d[1]d[n-2]+....+d[n-1][0] BigInteger d[]=new BigInteger[105]; public Tes(){ for(int i=0;i<105;i++){ d[i]=new BigInteger("0"); } Scanner sc=new Scanner(System.in); while(sc.hasNext()){ int n=sc.nextInt(); System.out.println(dp(n)); } } public BigInteger dp(int n){ if(n==0)return g(1); if(d[n].signum()>0)return d[n]; for(int i=0;i<=n-1;i++){ d[n]=d[n].add(dp(i).multiply(dp(n-i-1))); } return d[n]; } public BigInteger g(int x){ return new BigInteger(new Integer(x).toString()); } public BigInteger gs(String s){ return new BigInteger(s); } }
很经典的一道题,有人说这是卡特兰数,我也不知道是怎么用卡特兰数去解释,总之我是用递推做的
d[m][n]=m*d[m-1][n]+n*d[m][n-1] 其中M表示的是前M+N人中50元的个数,N是100元的个数,显然M+N的状态可以由M+N-1得来,而加的这个人可能是50元的,也可能是100元的.考虑50元,因为不同的排列算不同的结果,所以加的这个人可以跟前面的M-1个人交换位置,序列是不变的,所以要乘上一个M(加上放在第M+N个位置上的情况)
注意边界情况,m<n时d[m][n]=0,n=0时f[m][n]=m!
高精度,我是用Java实现的,附上主要代码
public BigInteger fac(int x){ if(x==0)return BigInteger.ONE; return fac(x-1).multiply(g(x)); } public BigInteger dp(int m,int n){ if(n==0)return fac(m); if(d[m][n]!=null)return d[m][n]; d[m][n]=new BigInteger("0"); if(m<n)d[m][n]=BigInteger.ZERO; else{ if(m>n)d[m][n]=dp(m-1,n).multiply(g(m)); d[m][n]=d[m][n].add(dp(m,n-1).multiply(g(n))); } return d[m][n]; } public BigInteger g(int x){ return new BigInteger(new Integer(x).toString()); }
跟上面的1130是一样的,只不过要乘上N!
2.3.7 HDU1134 Game of Connections
卡特兰数 F(n)=F(0)F(n-1)+F(1)F(n-2)+..F(n-1)F(0)
2.3.8 HDU1267 下沙的沙子有几粒
和上面的1133差不多,只不过不需要考虑排列的情况
所以d[i][j]=d[i-1][j]+d[i][j-1]; d[i][j]=0(i<j) 其中i表示H个数,j表示D个数