数论+快速幂 SRM 661 Div1 450: ColorfulLineGraphs

来源:互联网 发布:highcharts 更新数据 编辑:程序博客网 时间:2024/05/21 17:34

http://community.topcoder.com/stat?c=problem_statement&pm=13765

Problem Statement

Bob is going to create a graph with N nodes. The graph will be constructed in two steps. First, Bob will take N isolated vertices, label them 1 through N and color each of them using one of K colors. Then, Bob will add some directed edges to the graph. For each i between 2 and N, inclusive, Bob may choose a single value j < i such that the nodes i and j have different colors. If he does, he will add the edge from i to j to his graph. Note that Bob may choose not to add any edge from node i, even if there are some valid choices of j.

Two graphs are considered the same if they have the same node colors and the same set of edges.

You are given the longs N and K. You are also given an int M. Compute and return the number of different graphs Bob may construct, modulo M.

Definition

  • ClassColorfulLineGraphs
  • MethodcountWays
  • Parameterslong long , long long , int
  • Returnsint
  • Method signatureint countWays(long long N, long long K, int M)
(be sure your method is public)

Limits

  • Time limit (s)2.000
  • Memory limit (MB)256

Constraints

  • N will be between 1 and 1,000,000,000,000 (10^12), inclusive.
  • K will be between 1 and 1,000,000,000,000 (10^12), inclusive.
  • M will be between 2 and 1,000,000 (10^6), inclusive.

Test cases

    • N3
    • K2
    • M100000
    Returns24

    The 24 different graphs are shown below. In each picture, the vertices have labels 1, 2, 3 from the left to the right.

    • N15
    • K3
    • M1000000
    Returns510625
    • N100000
    • K100000
    • M999999
    Returns185185
    • N1000000000000
    • K6
    • M1000000
    Returns109376
    • N5000
    • K1000000000000
    • M314159
    1. Returns202996

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1. 题解
  2. The constraints, except for M are much larger than in the division 2 version. It is interesting M remains relatively small, as if O(M) or similar was intended. The large constraints for N and K suggest we might need to get creative, however.

    Imagine we are deciding what to do for the nodes in order from left to right (lowest index to highest). Imagine we already made decisions for the first i nodes. We know their colors and we know which edges (or lack of) we picked for each of them. Remember (from division 2) that when assigning things to do with the higher nodes, we only need to remember the number of nodes of each color that have been assigned, we don't need to know the edges. Let's count the number of decisions for node # i:

    • We may decide to use color #0. Then we have to pick an edges. We can pick no edge at all or we can connect node i to any node of a color different than 0. in which case we have 1+(icount(i,0)) options, where count(i,0) is the number of nodes of color 0 among the first i nodes.
    • For color 1: 1+icount(i,1).
    • ...
    • For color + k11+icount(i,k1).

    What happens if we add together all the options?

    1+icount(i,0)
    +1+icount(i,1)
    +1+icount(i,2)
    +...
    +1+icount(i,k1)

    k times 1, k times i and the sum of all counts:

    k+kij=0j<k(count(i,j))

    This is the interesting part: What is j=0j<k(count(i,j)) ? The sum of all the counts of colors among the first i nodes. This will be always equal to i. There are i nodes in total and the sum of all counts for each color will always be i. This means that the number of options for node i is: k+kii=k+i(k1). So in fact, the color choices before i are not relevant for the final result, only the total number of available colors. This way we can have an O(N) formula, just multiply k+i(k1) for each i : i=0i<N(i(k1)+k)

    N is still too large even for an O(N) so we need more improvements. This is where the small constraints on M can come into play. From i=0, to N1, the value imodM behaves in a cycle. So imagine M=3. For i=0,1,2,3,4,5,6,7, the values of imod3 will be: 0,1,2,0,1,2,0,1. Remember that (ab)modM=((amodM)(bmodM))modM, so i=0i<N(i(k1)+k)modM is equal to: i=0i<N((i(k1)+k)modM). Each (i(k1)+k)modM depends solely on i, more specifically imodM:

    (i(k1)+k)modM(((imodM)(k1)modM)+(kmodM))

    The only non-constant part is imodM. This part is cyclic and repeats every M parts. So back to the N=7,M=3 example: i=0,i=3,i=6 all will yield the same value of (i(k1)+k)modM. We can say the same about i=1,i=4 and i=2,i=5. We just need to use this cycle to our advantage.

    So for simplicity, let's name g(i)=(i(k1)+k)modM. We need to calculate:

    (g(0)g(1)g(2)...g(N1))modM

    We have the knowledge that for every pair ijmodMg(i)g(j)modM (The values of g(i) are repeated every M times). So imagine this:

    (g(0)g(1)g(2)...g(M1)g(M)g(M+1)g(M+2)...g(2M1)...g((N/M)1)
    g((N/M)M)g((N/M)M+1)...g((N/M)M+(NmodM)1)modM

    What we have here is the same M values are repeated over and over again, the first M values, the next M values and so and so. They will be repeated (N/M) times (integer, round down division). There will be some extra values depending if M divides N evenly. NmodM additional values (The remainder).

    (g(0)g(1)g(2)...g(M1)g(0)g(1)g(2)...g(M1)...g(0)g(1)g(2)...g(M1)
    g(0)g(1)...g((NmodM)1)modM

    The product g(0)g(1)g(2)...g(M1) is repeated exactly N/M times. So we can actually calculate the product of the first (N/M)M values by using the following:

    (g(0)g(1)g(2)...g(M1))N/M

    This requires O(M) time to calculate the product of the first M values, then we can use O(log(N/M)) time to calculate the power (for example, using exponentiation by squaring).

    Finally we need to multiply that to: g(0)g(1)...g((NmodM)1), This requires O(M) further steps. In total we have an O(O(log(N/M))+M) algorithm:

    long mod_pow(long x, long y, long M){    //exponentiation by squaring:    long r = 1;    long a = x;    while (y > 0) {        if (y % 2 == 1) {            r = (r * a) % M;          }        a = (a * a) % M;        y /= 2;    }    return r;} int countWays(long N, long K, int M){    long p = 1, q = 1;    // p will store product of all i < M    // q will store product of all i &ly; N%M    for (int i = 0; i < M; i++) {        long x = (i*(K - 1) + K) % M;        p = (p * x) % M;                    if (i < N%M) {            q = p;        }    }    return (mod_pow(p, N/M, M) * q) % M;}

    看完有没有很爽的感觉^-^


0 0
原创粉丝点击