Problem Description
我们定义如下矩阵:
1/1 1/2 1/3
1/2 1/1 1/2
1/3 1/2 1/1
矩阵对角线上的元素始终是1/1,对角线两边分数的分母逐个递增。
请求出这个矩阵的总和。
Input
每行给定整数N (N<50000),表示矩阵为 N*N.当N为0时,输入结束。
Output
输出答案,保留2位小数。
Sample Input
1
2
3
4
0
Sample Output
1.00
3.00
5.67
8.83
一看,大水题,马上来了个循环,然后计算 n/2的,得到复杂度O(n/2*n),提上去发现,TLE...我靠!
然后想了想,发现这题可以dp过去.恩....这下子肯定可以过了吧!!!?
dp的过程如下图:
n==2时:
1/1 1/2
1/2 1/1
n==3时:
1/1 1/2 1/3
1/2 1/1 1/2
1/3 1/2 1/1
容易看出
n==3时,dp[3] = dp[2] - dp[1] + dp[2] + 2*(1/n)
化简一下,推导出:
dp[n]=2*dp[n-1]-do[n-2] + (2/n)
接着快速的敲了Java代码,过了样例,提上去..一个大大的WA!!!!!!!!!!!!!!!!
然后把float改成了double,发现居然是两个不同的答案,再提交一次,还是WA.....(无奈,需要去恶补一下Java的浮点运算)
然后很无奈的换C敲一遍.....就AC了.....无奈无奈无奈
C Code:
#include <stdio.h> double dp[50001]; int main(){ int n; dp[1]=1; dp[2]=3; for(int i=3;i<=50000;i++){ dp[ i ] = 2 * dp[ i - 1 ] - dp[ i - 2 ] + ( 2.0 / i ); } while(scanf("%d",&n)==1 && n){ printf("%.2lf\n",dp[n]); } }
顺便给上Java的 WA code:
import java.util.Scanner; public class Main { public static double[] dp = new double[ 50001 ]; public static void dp() { dp[ 1 ] = 1; dp[ 2 ] = 3; for( int i = 3; i <= 50000; i++ ) { dp[ i ] = 2 * dp[ i - 1 ] - dp[ i - 2 ] + ( 2.0 / i ); } } public static void main( String[] args ) { Scanner sc = new Scanner( System.in ); dp(); while( sc.hasNext() ) { int n = sc.nextInt(); if( n == 0 ) return; else { System.out.printf( "%.2f\n", dp[ n ] ); } } } }
求Java老司机讲解下为何卡浮点呀。。。。
时间: 2024-11-07 12:46:30