Problem:
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']], skipTags: ["script","noscript","style","textarea","code"]}
});

F： 掛け算は楽しい - Multiplication Is Interesting -

物語

男子高生の難波列くんは、彼女の誕生日に数列をプレゼントしようと考えている。彼女は掛け算が大好きな女の子なので、難波くんは彼女にできるだけ多くの掛け算を楽しんてもらえるような数列をプレゼントしたいと思っている。しかし、計算結果が 2^{20} を超える値になると彼女の機嫌が途端に悪くなってしまう（通常の人類は 2^{20}という膨大な数を計算できないため、これでも彼女は随分と寛大な人であると言える）。彼女の機嫌を損なわないように、できるだけ多くの掛け算を楽しんでもらえる数列を難波くんが作ったので、あなたの仕事はその数列が彼女を十分に楽しませられるか検証するプログラムを作ることである。つまり、あなたの仕事は数列の連続する部分列の中で、部分列の総積が K を超えない最長の部分列の長さを答えるプログラムを作ることである。

問題

長さ N の非負実数列 S = s_1, s_2, ..., s_N と 非負実数 K がある。 あなたの仕事は、以下の条件を満たす S の連続する部分列のうち、次の条件を満たす最長の部分列の長さを求めることである。このとき、部分列の長さは 1 以上でなければならない。

S の連続する部分列 $T = s_\ell, \ldots, s_r$ について $\prod_{i = \ell, \ldots, r} s_i \leq$ Kを満たす。

もし条件を満たす部分列が一つも存在しないときは、 0 を出力せよ。

入力形式

入力は次の形式で与えられる．

N K
s_1
s_2
$\dots$
s_N

1 行目には数列の長さ N と 部分列の総積の上限 K が与えられる。続く N 行のうち、 i 行目では非負実数列 S の i 番目の実数 s_i が与えられる。

制約

1 \leq N \leq 100,000

0 \leq s_i \leq 2.00

0 \leq K \leq 1,048,576

N は整数、K と s_i は小数点第 3 位以下を含まない実数である

出力形式

S の部分列の総積が K を超えない最長の部分列の長さを 1 行に出力せよ。

入力例1

6 2.01
1.10
1.44
0.91
2.00
1.12
1.55

出力例1

3

入力例2

8 12.22
2.00
2.00
2.00
1.91
2.00
2.00
2.00
0.01

出力例2

8

Solution in C# (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;

// http://judge.u-aizu.ac.jp/onlinejudge/review.jsp


public class Test
{
	public static void Main()
	{

		  string[] str1 = Console.ReadLine().Split(' ');
		  int n = int.Parse(str1[0]); 
		  double k = double.Parse(str1[1]); 

		double[] a = new double[n];
		for(int i=0; i<n; i++){
			a[i] = double.Parse(Console.ReadLine());
		}
		  //Console.WriteLine("改行あり N = {0} P = {1} Ai = {2}", n, p, a);
		  Console.WriteLine(calc3(n,k,a));
		
		
	}

  public static int calc1(int n,double k,double[] a) {
	  double[] ra = new double[n];
	  double[] rb = new double[n];
	  bool[] pass = new bool[n+1];
	  for(int l=1;l<=n; l++){
		pass[l] = false;
		for(int i=0;i<=(n-l); i++){
			if(l==1) {
				ra[i] = a[i];
			} else {
				ra[i] = rb[i]*a[l+i-1];
			}
			if(ra[i] < k) pass[l] = true;
		}
		rb = ra;
	  }
	
	  int ret = 0;
	  for(int l=n;0<l; l--){
		if(pass[l]) {
			ret = l;
			break;
		}
	  }

	  return ret;
  }
  
  public static int calc3(int n,double k,double[] a) {
	  double[] lp = new double[n+1];
	  double[] rp = new double[n+1];
	  for(int i=0; i<=n; i++) {
		if((i<n)&&(a[i]<0.005)) return n;
//		lp[i] = (i==0) ? 1.0 : (lp[i-1]*a[i-1]);
//		rp[i] = (i==0) ? 1.0 : (rp[i-1]*a[n-i]);
		lp[i] = (i==0) ? 0.0 : (lp[i-1]+Math.Log(a[i-1]));
		rp[i] = (i==0) ? 0.0 : (rp[i-1]+Math.Log(a[n-i]));
	  }
	  if(k<0.005) return 0;
//	  double prod = lp[n]/(k+0.005);
	  double prod = lp[n]-Math.Log(k+0.005);
	  
	  double[] lp_max = new double[n+1];
	  double[] rp_max = new double[n+1];
	  double[] lp_min = new double[n+1];
	  double[] rp_min = new double[n+1];
	  for(int i=0; i<=n; i++) {
		if(i==0) {
			lp_max[0] = lp[0];
			rp_max[0] = rp[0];
			lp_min[0] = lp[0];
			rp_min[0] = rp[0];
		} else {
			lp_max[i] = (lp_max[i-1]<lp[i])? lp[i] : lp_max[i-1];
			rp_max[i] = (rp_max[i-1]<rp[i])? rp[i] : rp_max[i-1];
			lp_min[i] = (lp_min[i-1]>lp[i])? lp[i] : lp_min[i-1];
			rp_min[i] = (rp_min[i-1]>rp[i])? rp[i] : rp_min[i-1];
		}
	  }

	  int nmax = n;
	  int imin = 0;
	  int imax = 0;
	  for(int i=0; i<=n; i++) {
		if(prod < (lp_max[i]+rp_max[i])) {
			nmax = n-i;
			break;
		}
	  }
	  for(int i=0; i<=n; i++) {
		if(prod < (lp[i]+rp_max[n-i])) {
			imin = i;
			break;
		}
	  }
	  for(int i=0; i<=n; i++) {
		if(prod < (lp_max[n-i]+rp[i])) {
			imax = i;
			break;
		}
	  }

	  for(int l=nmax;0<l; l--){
		int q = n-l;
		int qx = q-imax;
		for(int i=imin;i<=qx; i++){
//			if(prod < (lp[i]*rp[q-i])) return l;
			if(prod < (lp[i]+rp[q-i])) return l;
		}
	  }

	  return 0;
  }



}