AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC032-C 列
■■■問題■■■
長さNの非負整数列 S=s1,s2, ・・・ ,sN と整数Kがあります。
あなたの仕事は、以下の条件を満たすSの連続する部分列のうち、
最も長いものの長さを求めることです。
部分列の長さは1以上の列でないといけません。
●その部分列に含まれる全ての要素の値の積は、K以下である。
もし条件を満たす部分列が一つも存在しないときは、0を出力してください。
■■■入力■■■
N K
s1
s2
・
・
sN
●1行目には、数列の長さを表す整数 N(1 <= N <= 10万) と
問題文中の整数 K(0 <= K <= 10億) が空白区切りで与えられる。
●2行目からの N行には、数列の各要素の値が与えられる。
そのうち i(1 <= i <= N) 行目には、si(0 <= si <= 10億) が書かれている。
■■■出力■■■
1行目に、含まれる全ての要素の値の積がK以下となる連続する部分列のうち最長のものの長さを出力せよ。
もし条件を満たす部分列が一つも存在しないときは、0を出力せよ。末尾の改行を忘れないこと。
C#のソース(Forループで左端をループする方法)
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("7 6");
WillReturn.Add("4");
WillReturn.Add("3");
WillReturn.Add("1");
WillReturn.Add("1");
WillReturn.Add("2");
WillReturn.Add("10");
WillReturn.Add("2");
//4
//部分列 S[2..5]=s2,s3,s4,s5 を選ぶと、
//積は 3×1×1×2 = 6 となり、K以下になります。
}
else if (InputPattern == "Input2") {
WillReturn.Add("6 10");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("0");
WillReturn.Add("10");
//6
}
else if (InputPattern == "Input3") {
WillReturn.Add("6 9");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("10");
WillReturn.Add("10");
//0
}
else if (InputPattern == "Input4") {
WillReturn.Add("4 0");
WillReturn.Add("1");
WillReturn.Add("2");
WillReturn.Add("3");
WillReturn.Add("4");
//0
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = InputList[0].Split(' ').Select(X => long.Parse(X)).ToArray();
long K = wkArr[1];
long[] SArr = InputList.Skip(1).Select(X => long.Parse(X)).ToArray();
long UB = SArr.GetUpperBound(0);
if (SArr.Contains(0)) {
Console.WriteLine(SArr.Length);
return;
}
long ProdVal = SArr[0];
long R = 0;
long Answer = 0;
for (long L = 0; L <= UB; L++) {
if (L > R) {
R = L;
ProdVal = SArr[L];
}
while (R + 1 <= UB && ProdVal * SArr[R + 1] <= K) {
ProdVal *= SArr[R + 1];
R++;
}
if (ProdVal <= K) {
Answer = Math.Max(Answer, R - L + 1);
}
ProdVal /= SArr[L];
}
Console.WriteLine(Answer);
}
}
C#のソース(Forループで右端をループする方法)
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static List<string> GetInputList()
{
var WillReturn = new List<string>();
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = InputList[0].Split(' ').Select(X => long.Parse(X)).ToArray();
long K = wkArr[1];
long[] SArr = InputList.Skip(1).Select(X => long.Parse(X)).ToArray();
long UB = SArr.GetUpperBound(0);
if (SArr.Contains(0)) {
Console.WriteLine(SArr.Length);
return;
}
long Answer = 0;
long L = 0;
long ProdVal = 1;
for (long R = 0; R <= UB; R++) {
ProdVal *= SArr[R];
while (ProdVal > K) {
if (L < R) {
ProdVal /= SArr[L];
L++;
}
else break;
}
if (ProdVal <= K) {
Answer = Math.Max(Answer, R - L + 1);
}
}
Console.WriteLine(Answer);
}
}
解説
尺取法で解いてます。