Approach 注文の量を各アイテムごとに計算する。量は、max(全てのアイテムの平均 + 係数 * 全てのアイテムの標準偏差, sqrt(min(期限の上限, 期限)) * 平均 + 係数 * 標準偏差) - 在庫。もし売値が買値より小さければ、量を 0.5 * (売値-買値) 減らす。ここで、係数は day が 1 から 100 に変化するとき、 3 から 0  に線形に変化する。期限の上限は day が 1 から 100 に変化するとき、 3 から 1  に線形に変化する。

後3%なんだったんだろう?


source code

import java.io.BufferedReader;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class ProductInventory {
private int day = 0;
private int[] buyPrice;
private int[] sellPrice;
private int[] expires;
private int numItems;
private int[][] stock;

private MeanHelper[] helpers;
private MeanHelper helpersAll;

public int init(int[] buy, int[] sell, int[] expiration) {
numItems = buy.length;
buyPrice = buy;
sellPrice = sell;
expires = expiration;

Utils.debug("numItems", numItems);
Utils.debug("buy", buy);
Utils.debug("sell", sell);
Utils.debug("expiration", expiration);

stock = new int[16][numItems];

helpers = new MeanHelper[numItems];
for (int i = 0; i < numItems; i++) {
helpers[i] = new MeanHelper();
}
helpersAll = new MeanHelper();

return 0;
}

public int[] order(int[] yesterday) {

int[] copyYesterday = Arrays.copyOf(yesterday, numItems);

for (int i = 0; i < numItems; i++) {
if (copyYesterday[i] == 0) {
continue;
}
for (int d = 0; d < 16; d++) {
while (copyYesterday[i] > 0 && stock[d][i] > 0) {
stock[d][i]--;
copyYesterday[i]--;
}
}
if (day > 0 && copyYesterday[i] > 0) {
Utils.debug(copyYesterday[i]);
}
}

for (int i = 0; i < numItems; i++) {
for (int d = 0; d < 15; d++) {
stock[d][i] = stock[d + 1][i];
}
stock[15][i] = 0;
}
day++;

if (day == 1) {
copyYesterday = Arrays.copyOf(yesterday, numItems);
for (int i = 0; i < numItems; i++) {
int[] day10 = new int[10];

for (int d = 0; copyYesterday[i]-- > 0; d = (d + 1) % 10) {
day10[d]++;
}

for (int d = 0; d < 10; d++) {
helpers[i].add(day10[d]);
helpersAll.add(day10[d]);
}
}
} else {
for (int i = 0; i < numItems; i++) {
helpers[i].add(yesterday[i]);
helpersAll.add(yesterday[i]);
}
}

double[] means = new double[numItems];
for (int i = 0; i < numItems; i++) {
means[i] = helpers[i].mean(0);
}

double[] sds = new double[numItems];
for (int i = 0; i < numItems; i++) {
sds[i] = helpers[i].standardDeviation(0);
}

double meanAllItem = helpersAll.mean(0);
double sdAllItem = helpersAll.standardDeviation(0);

int[] sumStocks = new int[numItems];
for (int d = 0; d < 16; d++) {
for (int i = 0; i < numItems; i++) {
sumStocks[i] += stock[d][i];
}
}

double coefSD = 3.0 + (0.0 - 3.0) * (day / 100.0);
double coefSDAll = 3.0 + (0.0 - 3.0) * (day / 100.0);
double coefExpi = 3.0 + (1.0 - 3.0) * (day / 100.0);

int[] orders = new int[numItems];
for (int i = 0; i < numItems; i++) {
double d = Math.max(meanAllItem + coefSDAll * sdAllItem, Math.sqrt(Math.min(coefExpi, expires[i])) * means[i] + coefSD * sds[i]) - sumStocks[i];
if (sellPrice[i] - buyPrice[i] < 0) {
d += 0.5 * (sellPrice[i] - buyPrice[i]);
}
d = Math.round(d);
d = Math.min(100, Math.max(0, d));
if (d > 0) {
orders[i] += (int) d;
}
}
for (int i = 0; i < numItems; i++) {
stock[expires[i]][i] += orders[i];
}
return orders;
}

public static void main(String[] args) throws IOException {
int n;
int[] buy;
int[] sell;
int[] expiration;
int[] yesterday;
int[] res;

try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) {
n = Integer.parseInt(in.readLine());
buy = new int[n];
for (int i = 0; i < n; i++) {
buy[i] = Integer.parseInt(in.readLine());
}

n = Integer.parseInt(in.readLine());
sell = new int[n];
for (int i = 0; i < n; i++) {
sell[i] = Integer.parseInt(in.readLine());
}

n = Integer.parseInt(in.readLine());
expiration = new int[n];
for (int i = 0; i < n; i++) {
expiration[i] = Integer.parseInt(in.readLine());
}

ProductInventory sol = new ProductInventory();
System.out.printf("%d\n", sol.init(buy, sell, expiration));
System.out.flush();

for (int k = 0; k < 100; k++) {
n = Integer.parseInt(in.readLine());
yesterday = new int[n];
for (int i = 0; i < n; i++) {
yesterday[i] = Integer.parseInt(in.readLine());
}

res = sol.order(yesterday);

System.out.printf("%d\n", res.length);
for (int i = 0; i < res.length; i++) {
System.out.printf("%d\n", res[i]);
}
System.out.flush();
}
}
}
}

class MeanHelper {
private double max;
private double min;
private double sum;
private double sumSquared;
private double sumCubed;
private double sumFourth;
private int count;

public MeanHelper() {
clear();
}

public void add(double value) {
max = Math.max(max, value);
min = Math.min(min, value);
sum += value;
double valueSquared = value * value;
sumSquared += valueSquared;
sumCubed += valueSquared * value;
sumFourth += valueSquared * valueSquared;
count++;
}

public void add(double value, double number) {
max = Math.max(max, value);
min = Math.min(min, value);
sum += value * number;
double valueSquared = value * value;
sumSquared += valueSquared * number;
sumCubed += valueSquared * value * number;
sumFourth += valueSquared * valueSquared * number;
count += number;
}

public double kurtosis(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
double sigma = standardDeviation(0);
if (sigma == 0) {
return 0;
}
double mu = mean(0);
return (sumFourth - 4.0 * mu * sumCubed + 6.0 * mu * mu * sumSquared - 3.0 * mu * mu * mu * sum) / count / (sigma * sigma * sigma * sigma);
}

public double skewness(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
double sigma = standardDeviation(0);
if (sigma == 0) {
return 0;
}
double mu = mean(0);
return (sumCubed - 3.0 * mu * sumSquared + 2.0 * mu * mu * sum) / count / (sigma * sigma * sigma);
}

public double mean() {
if (isEmpty()) {
throw new AssertionError();
}
return sum / count;
}

public double mean(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
return sum / count;
}

public double sumOfSquaredError() {
if (isEmpty()) {
throw new AssertionError();
}
return sumSquared - sum * sum / count;
}

public double sumOfSquaredError(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
return sumSquared - sum * sum / count;
}

public double variance() {
if (isEmpty()) {
throw new AssertionError();
}
double E_XX = sumSquared / count;
double E_X = sum / count;
return E_XX - E_X * E_X;
}

public double variance(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
double E_XX = sumSquared / count;
double E_X = sum / count;
return E_XX - E_X * E_X;
}

public double unbiasedVariance() {
if (count - 1 == 0) {
throw new AssertionError();
}
return (count * variance()) / (count - 1);
}

private double unbiasedVariance(double defaultValue) {
if (count - 1 == 0) {
return defaultValue;
}
return (count * variance()) / (count - 1);
}

public double standardDeviation() {
return Math.sqrt(variance());
}

public double standardDeviation(double defaultValue) {
return Math.sqrt(variance(defaultValue));
}

public double unbiasedStandardDeviation() {
return Math.sqrt(unbiasedVariance());
}

public double unbiasedStandardDeviation(double defaultValue) {
return Math.sqrt(unbiasedVariance(defaultValue));
}

public boolean isEmpty() {
return count == 0;
}

public void clear() {
max = Double.NEGATIVE_INFINITY;
min = Double.POSITIVE_INFINITY;
sum = 0;
sumSquared = 0;
sumCubed = 0;
sumFourth = 0;
count = 0;
}

public double max() {
if (isEmpty()) {
throw new AssertionError();
}
return max;
}

public double max(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
return max;
}

public double min() {
if (isEmpty()) {
throw new AssertionError();
}
return min;
}

public double min(double defaultValue) {
if (isEmpty()) {
return defaultValue;
}
return min;
}

public int count() {
return count;
}

public double sum() {
return sum;
}

public double sumSquared() {
return sumSquared;
}
}

final class Utils {
private Utils() {
}

public static final void debug(Object... o) {
System.err.println(toString(o));
}

public static final String toString(Object... o) {
return Arrays.deepToString(o);
}

}