某岛

… : "…アッカリ~ン . .. . " .. .
September 17, 2014

SRM 626

http://apps.topcoder.com/wiki/display/tc/SRM+626

900. ReflectiveRectangle

Brief description:

。给定一个长 sideA 宽 sideB 的矩阵。。
从左下角发射一枚光线,要求恰好在墙壁反射 n 次后落入右上角,且中途不能经过 corner。。。

Analysis:

首先 n 必须是偶数。。
设在横轴与纵轴分别反弹 a, b 次
那么平铺后的长宽分别为 (a+1)sideA, (b+1)sideB。。。
a+b == n,gcd(a+1, b+1) = 1
——————

然后显然是一个莫比乌斯反演。。
。。。

s2(n) = 1^2 + 2^2 + \ldots + n^2 = n*(n+1)*(2*n+1)/6 ...
g(d) = [d | gcd(i, n-i)] * (i^2)  =  sqr(d) * s2(n/d);
f(d) = [d = gcd(i, n-i)] * (i^2)
...

卧槽我真是蠢哭了。。我居然写朴素的时候有一个 LL 没加。。一直样例没出来。。。
。。。艹。瞬间数论白学了。。(速度写一个朴素的策略本身是没问题的。。。但是处理的太不谨慎了。。)

const int PMAX = 46341;

vector<int> P; bitset<PMAX> isC; int mu[PMAX];

void sieve(){
    mu[1] = 1; FOR(i, 2, PMAX){
        if (!isC[i]) P.PB(i), mu[i] = -1;
        for (int j=0;j<SZ(P)&&i*P[j]<PMAX;++j){
            isC[i*P[j]]=1; if (!(i%P[j])){
                mu[i*P[j]] = 0;
                break;
            } else{
                mu[i*P[j]] = -mu[i];
            }
        }
    }
}

VII fac; void fact(int x){
    int z = x; fac.clear(); ECH(it, P) if (!(x%*it)){
        int c=1; x/=*it; while (!(x%*it)) x/=*it, ++c;
        fac.PB(MP(*it, c));
    }
    if (x!=1) fac.PB(MP(x, 1));
}

Int ans; int n;

Int s2(Int n){
    return n*(n+1)*(2*n+1)/6;
}

Int f(Int d){
    return s2(d)*sqr(Int(n/d));
}

void gao(int k = 0, int c = 0, int d = 1){
    if (k == SZ(fac)){
        if (c&1) ans -= f(n/d);
        else ans += f(n/d);
    }
    else{
        gao(k+1, c, d);
        gao(k+1, c+1, d*fac[k].fi);
    }
}

class ReflectiveRectangle {
public:
int findSum(int sideA, int sideB, int n) {
        if (n&1) return 0; Int cof = ((LL)sideA*sideA+(LL)sideB*sideB)%MOD;
        ans = 0, n += 2, ::n = n;

        REP_1(a, n){
            int b = n-a; if (gcd(a, b) != 1) continue;
            ans += sqr((Int)a);
        }

        //cout << "b: " << n << endl;
        //sieve(); fact(n); gao();
        return ans * cof;
}
};