結果

問題 No.493 とても長い数列と文字列(Long Long Sequence and a String)
ユーザー yosupotyosupot
提出日時 2017-03-10 22:48:16
言語 D
(dmd 2.106.1)
結果
AC  
実行時間 2 ms / 800 ms
コード長 9,601 bytes
コンパイル時間 3,779 ms
コンパイル使用メモリ 142,404 KB
実行使用メモリ 6,944 KB
最終ジャッジ日時 2024-06-12 18:19:24
合計ジャッジ時間 6,507 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
6,816 KB
testcase_01 AC 1 ms
6,816 KB
testcase_02 AC 1 ms
6,944 KB
testcase_03 AC 1 ms
6,940 KB
testcase_04 AC 1 ms
6,940 KB
testcase_05 AC 1 ms
6,944 KB
testcase_06 AC 1 ms
6,940 KB
testcase_07 AC 1 ms
6,944 KB
testcase_08 AC 1 ms
6,944 KB
testcase_09 AC 1 ms
6,940 KB
testcase_10 AC 1 ms
6,940 KB
testcase_11 AC 1 ms
6,944 KB
testcase_12 AC 1 ms
6,944 KB
testcase_13 AC 1 ms
6,940 KB
testcase_14 AC 1 ms
6,940 KB
testcase_15 AC 2 ms
6,940 KB
testcase_16 AC 1 ms
6,944 KB
testcase_17 AC 1 ms
6,940 KB
testcase_18 AC 1 ms
6,944 KB
testcase_19 AC 1 ms
6,944 KB
testcase_20 AC 1 ms
6,944 KB
testcase_21 AC 1 ms
6,940 KB
testcase_22 AC 2 ms
6,944 KB
testcase_23 AC 1 ms
6,940 KB
testcase_24 AC 1 ms
6,940 KB
testcase_25 AC 1 ms
6,940 KB
testcase_26 AC 1 ms
6,940 KB
testcase_27 AC 1 ms
6,944 KB
testcase_28 AC 1 ms
6,940 KB
testcase_29 AC 1 ms
6,940 KB
testcase_30 AC 2 ms
6,940 KB
testcase_31 AC 1 ms
6,940 KB
testcase_32 AC 1 ms
6,940 KB
testcase_33 AC 1 ms
6,944 KB
testcase_34 AC 1 ms
6,944 KB
testcase_35 AC 1 ms
6,940 KB
testcase_36 AC 1 ms
6,944 KB
testcase_37 AC 1 ms
6,940 KB
testcase_38 AC 1 ms
6,944 KB
testcase_39 AC 1 ms
6,940 KB
testcase_40 AC 1 ms
6,940 KB
testcase_41 AC 1 ms
6,944 KB
testcase_42 AC 1 ms
6,944 KB
testcase_43 AC 1 ms
6,944 KB
testcase_44 AC 1 ms
6,940 KB
testcase_45 AC 1 ms
6,940 KB
testcase_46 AC 1 ms
6,940 KB
testcase_47 AC 1 ms
6,944 KB
testcase_48 AC 1 ms
6,944 KB
testcase_49 AC 2 ms
6,944 KB
testcase_50 AC 1 ms
6,940 KB
testcase_51 AC 1 ms
6,940 KB
testcase_52 AC 1 ms
6,944 KB
testcase_53 AC 0 ms
6,940 KB
testcase_54 AC 1 ms
6,944 KB
testcase_55 AC 1 ms
6,944 KB
testcase_56 AC 1 ms
6,944 KB
testcase_57 AC 1 ms
6,940 KB
testcase_58 AC 1 ms
6,944 KB
testcase_59 AC 1 ms
6,944 KB
testcase_60 AC 1 ms
6,940 KB
testcase_61 AC 1 ms
6,944 KB
testcase_62 AC 1 ms
6,940 KB
testcase_63 AC 1 ms
6,944 KB
testcase_64 AC 1 ms
6,940 KB
testcase_65 AC 1 ms
6,940 KB
testcase_66 AC 2 ms
6,944 KB
testcase_67 AC 1 ms
6,940 KB
testcase_68 AC 1 ms
6,940 KB
testcase_69 AC 1 ms
6,940 KB
testcase_70 AC 1 ms
6,940 KB
testcase_71 AC 1 ms
6,944 KB
testcase_72 AC 1 ms
6,944 KB
testcase_73 AC 1 ms
6,944 KB
testcase_74 AC 1 ms
6,940 KB
testcase_75 AC 1 ms
6,944 KB
testcase_76 AC 1 ms
6,940 KB
testcase_77 AC 1 ms
6,944 KB
testcase_78 AC 1 ms
6,940 KB
testcase_79 AC 1 ms
6,944 KB
testcase_80 AC 1 ms
6,940 KB
testcase_81 AC 1 ms
6,944 KB
testcase_82 AC 1 ms
6,940 KB
testcase_83 AC 1 ms
6,940 KB
testcase_84 AC 1 ms
6,944 KB
testcase_85 AC 1 ms
6,944 KB
testcase_86 AC 1 ms
6,944 KB
testcase_87 AC 1 ms
6,940 KB
testcase_88 AC 1 ms
6,944 KB
testcase_89 AC 1 ms
6,944 KB
testcase_90 AC 2 ms
6,940 KB
testcase_91 AC 1 ms
6,940 KB
testcase_92 AC 1 ms
6,944 KB
testcase_93 AC 1 ms
6,944 KB
testcase_94 AC 1 ms
6,940 KB
testcase_95 AC 2 ms
6,944 KB
testcase_96 AC 1 ms
6,940 KB
testcase_97 AC 1 ms
6,940 KB
testcase_98 AC 1 ms
6,944 KB
testcase_99 AC 1 ms
6,944 KB
testcase_100 AC 1 ms
6,940 KB
testcase_101 AC 1 ms
6,944 KB
testcase_102 AC 1 ms
6,944 KB
testcase_103 AC 1 ms
6,944 KB
testcase_104 AC 2 ms
6,940 KB
testcase_105 AC 1 ms
6,940 KB
testcase_106 AC 1 ms
6,940 KB
testcase_107 AC 1 ms
6,944 KB
testcase_108 AC 2 ms
6,940 KB
testcase_109 AC 1 ms
6,940 KB
testcase_110 AC 1 ms
6,944 KB
testcase_111 AC 1 ms
6,940 KB
testcase_112 AC 1 ms
6,940 KB
testcase_113 AC 1 ms
6,944 KB
testcase_114 AC 1 ms
6,944 KB
testcase_115 AC 1 ms
6,940 KB
testcase_116 AC 1 ms
6,944 KB
testcase_117 AC 1 ms
6,940 KB
testcase_118 AC 1 ms
6,944 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

/+ dub.sdl:
    name "A"
    dependency "dcomp" version=">=0.6.0"
+/

import std.stdio, std.range, std.conv, std.algorithm;
// import dcomp.scanner;
// import dcomp.modint;
alias Mint = ModInt!(10^^9 + 7);

long[] len;
long lenInit(int k) {
    len = new long[](k+1);
    long ba = 1;
    len[1] = 1;
    foreach (long i; 2..k+1) {
        ba = 2*ba + (i*i).to!string.length;
        len[i] = ba;
    }
    return ba;
}

long calcSumNaive(long l, long r, string s) {
    l = max(l, 0L);
    r = min(r, s.length);
    long sm = 0;
    foreach (long i, c; s) {
        int u = c - '0';
        if (u == 0) u = 10;
        if (l <= i && i < r) {
            sm += u;
        }
    }
    return sm;
}

long[] sumDP;
bool[] sumUsed;
static this() {
    sumDP = new long[100];
    sumUsed = new bool[100];
}

long calcSum(long l, long r, int k) {
    l = max(l, 0L);
    r = min(r, len[k]);
    if (r <= l) return 0;
    bool full = (l == 0 && r == len[k]);
    if (full && sumUsed[k]) return sumDP[k];
    if (full) sumUsed[k] = true;
    long ans = 0;

    ans += calcSum(l, r, k-1);

    long di = len[k-1];
    string s = (k*k).to!string;
    ans += calcSumNaive(l-di, r-di, s);

    di += s.length;
    ans += calcSum(l-di, r-di, k-1);

    if (full) sumDP[k] = ans;
    return ans;
}


Mint calcMulNaive(long l, long r, string s) {
    l = max(l, 0L);
    r = min(r, s.length);
    Mint sm = 1;
    foreach (long i, c; s) {
        int u = c - '0';
        if (u == 0) u = 10;
        if (l <= i && i < r) {
            sm *= Mint(u);
        }
    }
    return sm;
}

Mint[] mulDP;
bool[] mulUsed;
static this() {
    mulDP = new Mint[100];
    mulUsed = new bool[100];
}

Mint calcMul(long l, long r, int k) {
    l = max(l, 0L);
    r = min(r, len[k]);
    if (r <= l) return Mint(1);
    bool full = (l == 0 && r == len[k]);
    if (full && mulUsed[k]) return mulDP[k];
    if (full) mulUsed[k] = true;

    Mint ans = 1;

    ans *= calcMul(l, r, k-1);

    long di = len[k-1];
    string s = (k*k).to!string;
    ans *= calcMulNaive(l-di, r-di, s);

    di += s.length;
    ans *= calcMul(l-di, r-di, k-1);

    if (full) mulDP[k] = ans;

    return ans;
}

int main() {
    auto sc = new Scanner(stdin);
    int k; long l, r;
    sc.read(k, l, r); l--;
    k = min(k, 60);
    lenInit(k);
    if (len[k] < r) {
        writeln("-1");
        return 0;
    }
    auto sm = calcSum(l, r, k);
    auto ml = calcMul(l, r, k);
    writeln(sm, " ", ml);
    return 0;
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/modint.d */
// module dcomp.modint;

// import dcomp.numeric.primitive;

struct ModInt(uint MD) if (MD < int.max) {
    import std.conv : to;
    uint v;
    this(int v) {this(long(v));}
    this(long v) {this.v = (v%MD+MD)%MD;}
    static auto normS(uint x) {return (x<MD)?x:x-MD;}
    static auto make(uint x) {ModInt m; m.v = x; return m;}
    auto opBinary(string op:"+")(ModInt r) const {return make(normS(v+r.v));}
    auto opBinary(string op:"-")(ModInt r) const {return make(normS(v+MD-r.v));}
    auto opBinary(string op:"*")(ModInt r) const {return make( (long(v)*r.v%MD).to!uint );}
    auto opBinary(string op:"/")(ModInt r) const {return this*inv(r);}
    auto opOpAssign(string op)(ModInt r) {return mixin ("this=this"~op~"r");}
    static ModInt inv(ModInt x) {return ModInt(extGcd!int(x.v, MD)[0]);}
    string toString() {return v.to!string;}
}

unittest {
    static assert( is(ModInt!(uint(1000000000) * 2))); //not overflow
    static assert(!is(ModInt!(uint(1145141919) * 2))); //overflow!
    alias Mint = ModInt!(10^^9+7);
    // negative check
    assert(Mint(-1).v == 10^^9 + 6);
    assert(Mint(-1L).v == 10^^9 + 6);

    Mint a = 48;
    Mint b = Mint.inv(a);
    assert(b.v == 520833337);

    Mint c = Mint(15);
    Mint d = Mint(3);
    assert((c/d).v == 5);
}

struct DModInt(string name) {
    import std.conv : to;
    static uint MD;
    uint v;
    this(int v) {this(long(v));}
    this(long v) {this.v = ((v%MD+MD)%MD).to!uint;}
    auto normS(uint x) {return (x<MD)?x:x-MD;}
    auto make(uint x) {DModInt m; m.MD = MD; m.v = x; return m;}
    auto opBinary(string op:"+")(DModInt r) {
        return make(normS(v+r.v));
    }
    auto opBinary(string op:"-")(DModInt r) {
        return make(normS(v+MD-r.v));
    }
    auto opBinary(string op:"*")(DModInt r) {
        return make((long(v)*r.v%MD).to!uint);
    }
    auto opBinary(string op:"/")(DModInt r) {
        return this*inv(r);
    }
    auto opOpAssign(string op)(DModInt r) {return mixin ("this=this"~op~"r");}
    static DModInt inv(DModInt x) {
        return DModInt(extGcd!int(x.v, MD)[0]);
    }
    string toString() {return v.to!string;}
}

unittest {
    alias Mint = DModInt!("default");
    Mint.MD = 10^^9 + 7;
    //negative check
    assert(Mint(-1).v == 10^^9 + 6);
    assert(Mint(-1L).v == 10^^9 + 6);
    Mint a = Mint(48);
    Mint b = Mint.inv(a);
    assert(b.v == 520833337);
    Mint c = Mint(15);
    Mint d = Mint(3);
    assert((c/d).v == 5);
}

template isModInt(T) {
    const isModInt =
        is(T : ModInt!MD, uint MD) || is(S : DModInt!S, string s);
}


T[] factTable(T)(size_t length) if (isModInt!T) {
    import std.range : take, recurrence;
    import std.array : array;
    return T(1).recurrence!((a, n) => a[n-1]*T(n)).take(length).array;
}

// optimize
T[] invFactTable(T)(size_t length) if (isModInt!T) {
    import std.algorithm : map, reduce;
    import std.range : take, recurrence, iota;
    import std.array : array;
    auto res = new T[length];
    res[$-1] = T(1) / iota(1, length).map!T.reduce!"a*b";
    foreach_reverse (i, v; res[0..$-1]) {
        res[i] = res[i+1] * T(i+1);
    }
    return res;
}

T[] invTable(T)(size_t length) if (isModInt!T) {
    auto f = factTable!T(length);
    auto invf = invFactTable!T(length);
    auto res = new T[length];
    foreach (i; 1..length) {
        res[i] = invf[i] * f[i-1];
    }
    return res;
}

unittest {
    import std.stdio;
    alias Mint = ModInt!(10^^9 + 7);
    auto r = factTable!Mint(20);
    Mint a = 1;
    assert(r[0] == Mint(1));
    foreach (i; 1..20) {
        a *= Mint(i);
        assert(r[i] == a);
    }
    auto p = invFactTable!Mint(20);
    foreach (i; 1..20) {
        assert((r[i]*p[i]).v == 1);
    }
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/scanner.d */
// module dcomp.scanner;

class Scanner {
    import std.stdio : File;
    import std.conv : to;
    import std.range : front, popFront, array, ElementType;
    import std.array : split;
    import std.traits : isSomeChar, isStaticArray, isArray; 
    import std.algorithm : map;
    File f;
    this(File f) {
        this.f = f;
    }
    string[] buf;
    private bool succ() {
        while (!buf.length) {
            if (f.eof) return false;
            buf = f.readln.split;
        }
        return true;
    }
    private bool readSingle(T)(ref T x) {
        if (!succ()) return false;
        static if (isArray!T) {
            alias E = ElementType!T;
            static if (isSomeChar!E) {
                //string or char[10] etc
                x = buf.front;
                buf.popFront;
            } else {
                static if (isStaticArray!T) {
                    //static
                    assert(buf.length == T.length);
                }
                x = buf.map!(to!E).array;
                buf.length = 0;                
            }
        } else {
            x = buf.front.to!T;
            buf.popFront;            
        }
        return true;
    }
    int read(T, Args...)(ref T x, auto ref Args args) {
        if (!readSingle(x)) return 0;
        static if (args.length == 0) {
            return 1;
        } else {
            return 1 + read(args);
        }
    }
}

unittest {
    import std.path : buildPath;
    import std.file : tempDir;
    import std.algorithm : equal;
    import std.stdio : File;
    string fileName = buildPath(tempDir, "kyuridenanmaida.txt");
    auto fout = File(fileName, "w");
    fout.writeln("1 2 3");
    fout.writeln("ab cde");
    fout.writeln("1.0 1.0 2.0");
    fout.close;
    Scanner sc = new Scanner(File(fileName, "r"));
    int a;
    int[2] b;
    char[2] c;
    string d;
    double e;
    double[] f;
    sc.read(a, b, c, d, e, f);
    assert(a == 1);
    assert(equal(b[], [2, 3]));
    assert(equal(c[], "ab"));
    assert(equal(d, "cde"));
    assert(e == 1.0);
    assert(equal(f, [1.0, 2.0]));
}
/* IMPORT /home/yosupo/Program/dcomp/source/dcomp/numeric/primitive.d */
// module dcomp.numeric.primitive;

import std.traits;

T pow(T, U)(T x, U n) if (!isFloatingPoint!T && isIntegral!U) {
    return pow(x, n, T(1));
}

T pow(T, U)(T x, U n, T e) if (isIntegral!U) {
    while (n) {
        if (n & 1) e *= x;
        x *= x;
        n /= 2;
    }
    return e;
}

unittest {
    assert(pow(3, 5) == 243);
    assert(pow(3, 5, 2) == 486);
}

T lcm(T)(in T a, in T b) {
    import std.numeric : gcd;
    return a / gcd(a,b) * b;
}

unittest {
    assert(lcm(2, 4) == 4);
    assert(lcm(3, 5) == 15);
    assert(lcm(1, 1) == 1);
    assert(lcm(0, 100) == 0);
}

//a*T[0]+b*T[1]=T[2], T[2]=gcd
//todo: to binary extgcd
T[3] extGcd(T)(in T a, in T b) 
if (!isIntegral!T || isSigned!T) //unsignedはNG
{
    if (b==0) {
        return [1, 0, a];
    } else {
        auto e = extGcd(b, a%b);
        return [e[1], e[0]-a/b*e[1], e[2]];
    }
}

unittest {
    import std.numeric : gcd;
    foreach (i; 0..100) {
        foreach (j; 0..100) {
            auto e = extGcd(i, j);
            assert(e[2] == gcd(i, j));
            assert(e[0] * i + e[1] * j == e[2]);
        }
    }
}
0