1. 程式人生 > >Ctrl-C Ctrl-V

Ctrl-C Ctrl-V

題目1 : Ctrl-C Ctrl-V

時間限制:10000ms

單點時限:1000ms

記憶體限制:256MB

描述

Yor are bored. So you open a notepad and keep pressing letter 'A' to type a lot of 'A's into the text area.

Suddenly an idea come out. If you can do the following 4 kinds of operations N times, how many 'A's you can type into the text area?    

- A: Type a letter A into the text area

- Ctrl-A: Select all the letters in the text area

- Ctrl-C: Copy the selected letters into clipboard  

- Ctrl-V: Paste the letters from clipboard into the text area

Assume N=7 you can get 9 'A's by doing following operations: A, A, A, Ctrl-A, Ctrl-C, Ctrl-V, Ctrl-V.  

輸入

An integer N. (1 <= N <= 1000000000)

輸出

The maximum number of 'A's you can type into the text area. Note the answer may be very large so output the answer modulo 1000000007.

樣例輸入

7

樣例輸出

9

首先,對於最優方案,Ctrl-A + Ctrl-C + 若干個Ctrl-V一定是連在一起的。

例如 Ctrl-A + A + Ctrl-C + Ctrl-V,一定不如把A放在Ctrl-A之前,即: A + Ctrl-A + Ctrl-C + Ctrl-V

Ctrl-A + Ctrl-C + A + Ctrl-V 一定不如 A + Ctrl-A + Ctrl-C + Ctrl-V。

我們用f[i]表示i個操作最多能輸出多少個A。對於最優解,最後一個操作一定是A或者Ctrl-V。

如果最後一個操作是A,則f[i] = f[i-1] + 1;如果最後一個操作是Ctrl-V,我們假設最後一共有連續K個Ctrl-V,則f[i] = f[i-2-K] * (K+1)。

於是我們可以得到一個O(N^2)的DP演算法。

當然本題資料範圍很大,O(N^2)的DP沒辦法通過所有的資料。不過我們可以用這個演算法得到前若干項的值。例如N=1..25的答案如下:

1 1
2 2
3 3
4 4
5 5
6 6
7 9
8 12
9 16
10 20
11 27
12 36
13 48
14 64
15 81
16 108
17 144
18 192
19 256
20 324
21 432
22 576
23 768
24 1024
25 1296

可以看出,對於N >= 16,f[N] = f[N - 5] * 4。換句話說,當N足夠大的時候,最優的策略就是用Ctrl-A + Ctrl-C + Ctrl-V + Ctrl-V + Ctrl-V 5個操作把長度變成4倍。

 

import java.util.Scanner;

public class Main {
class Node {
    int use;
    int count;
    int paste;

    Node(int use, int count, int paste) {
        this.use = use;
        this.count = count;
        this.paste = paste;
    }
}

long mod = 1000000007;
long[] a = new long[100];
int[] last = new int[a.length];

long pow(long x, int y) {
    if (y == 0) return 1;
    if (y == 1) return x;
    long z = pow(x, y / 2);
    if (y % 2 == 0) {
        return z * z % mod;
    } else {
        return z * z * x % mod;
    }
}

long solve(int x) {
    if (x <= 16) return a[x];
    int power = (x - 11) / 5;
    int which = (x - 11) % 5;
    long ans = a[11 + which] * pow(4, power) % mod;
    return ans;
}

Main() {
    Scanner cin = new Scanner(System.in);
    int x = cin.nextInt();

    for (int i = 0; i < 6; i++) {
        a[i] = i;
    }
    for (int i = 6; i <= 16; i++) {
        for (int j = 1; j < i - 2; j++) {
            long now = a[j] * (i - 1 - j);
            if (now > a[i]) {
                a[i] = now;
                last[i] = j;
            }
        }
    }
    System.out.println(solve(x));
}

public static void main(String[] args) {
    new Main();
}
}