結果

問題 No.377 背景パターン
ユーザー mudbdbmudbdb
提出日時 2016-06-08 21:38:37
言語 C90
(gcc 11.4.0)
結果
AC  
実行時間 832 ms / 5,000 ms
コード長 3,559 bytes
コンパイル時間 570 ms
コンパイル使用メモリ 28,144 KB
実行使用メモリ 4,384 KB
最終ジャッジ日時 2023-07-30 08:40:48
合計ジャッジ時間 3,310 ms
ジャッジサーバーID
(参考情報)
judge13 / judge5
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,376 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 1 ms
4,380 KB
testcase_03 AC 1 ms
4,376 KB
testcase_04 AC 0 ms
4,376 KB
testcase_05 AC 0 ms
4,384 KB
testcase_06 AC 1 ms
4,376 KB
testcase_07 AC 0 ms
4,376 KB
testcase_08 AC 1 ms
4,380 KB
testcase_09 AC 0 ms
4,376 KB
testcase_10 AC 1 ms
4,376 KB
testcase_11 AC 1 ms
4,376 KB
testcase_12 AC 1 ms
4,376 KB
testcase_13 AC 5 ms
4,380 KB
testcase_14 AC 2 ms
4,380 KB
testcase_15 AC 1 ms
4,376 KB
testcase_16 AC 823 ms
4,376 KB
testcase_17 AC 832 ms
4,380 KB
testcase_18 AC 1 ms
4,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <stdio.h>
#include <stdlib.h>
typedef long long int ll;
int H,W,K;
ll gcd(ll a, ll b)
{
  int c;
  if (a < b) {
    c = a;
    a = b;
    b = c;
  }
  while (b != 0) {
    c = a%b;
    a = b;
    b = c;
  }
  return a;
}
ll lcm(ll a, ll b)
{
  return a*b/gcd(a,b);
}
int M = 1000000007;
// K^e (mod M)の計算
ll pow_mod_K(ll K, ll e)
{
  if (K == 1) {
    return 1;
  }

  // K^(2^0), K^(2^1), ... , K^(2^n)
  static ll *KE = 0;
  int sz = 0;
  int i;
  if (KE == 0) {
    i = H;
    while (i != 0) { sz++; i>>=1; }
    sz++;
    i = W;
    while (i != 0) { sz++; i>>=1; }
    sz++;

    KE = (ll *)malloc(sizeof(ll)*sz);
    KE[0] = K%M;
    for (i=1; i<sz; i++) KE[i] = (KE[i-1]*KE[i-1])%M;
  }

  ll K2 = 1;
  i = 0;
  while (e != 0) {
    if (e&1) {
      K2 *= KE[i];
      K2 %= M;
    }
    i++;
    e>>=1;
  }
  return K2;
}
// B^e (mod M)の計算
ll pow_mod(ll B, ll e)
{
  if (B == 1) {
    return 1;
  }
  ll B2 = 1;
  B %= M;
  while (e != 0) {
    if (e&1) {
      B2 *= B;
      B2 %= M;
    }
    B = B*B;
    B %= M;
    e>>=1;
  }
  return B2;
}
// (2^3)^9 < 10^9 < (2^4)^9
ll P[4*9];
int E[4*9];
int Pend = 0;
int factor(ll N)
{
  ll p;
  int e;
  p=2;
  if (N%p == 0) {
    P[Pend] = p;
    e=1;
    for (N/=p; N%p==0; N/=p) e++;
    E[Pend] = e;
    Pend++;
  }
  for (p=3; p*p<=N; p+=2) {
    if (N%p == 0) {
      P[Pend] = p;
      e=1;
      for (N/=p; N%p==0; N/=p) e++;
      E[Pend] = e;
      Pend++;
    }
  }
  if (N != 1) {
    P[Pend] = N;
    E[Pend] = 1;
    Pend++;
  }
  return 0;
}
// e >= 0
// d^e
ll pwr(ll d, int e)
{
  if (d == 1) {
    return 1;
  }
  ll dd = 1;
  while (e != 0) {
    if (e&1) {
      dd *= d;
    }
    d = d*d;
    e>>=1;
  }
  return dd;
}
int cmpr(const void *a, const void *b)
{
  if (*(ll *)a < *(ll *)b) {
    return -1;
  } else if (*(ll *)a > *(ll *)b) {
    return 1;
  } else {
    return 0;
  }
}
// Nの全約数生成
void initD(int N, ll **aD, int *aDsz)
{
  Pend = 0;
  factor(N);

  int i;
  ll *D;
  int Dsz = 1;
  for (i=0; i<Pend; i++) Dsz *= (E[i]+1);
  D = (ll *)malloc(sizeof(ll)*Dsz);
  for (i=0; i<Dsz; i++) D[i] = 1;

  int j,k,l;
  int rpt = 1;
  for (i=0; i<Pend; i++) {
    for (j=0, k=0; j<Dsz; ) {
      for (l=0; l<rpt; l++) {
        D[j] *= pwr(P[i],k);
        j++;
      }
      k++;
      k %= (E[i]+1);
    }
    rpt *= (E[i]+1);
  }
  qsort(D, Dsz, sizeof(ll), cmpr);
  (*aD) = D;
  (*aDsz) = Dsz;
}
ll T_mod(ll x, int pos, ll *D, int Dsz, ll *DP)
{
  ll T;
  if (DP[pos] == 0) {
    T = D[Dsz-1]/x;
    int i;
    for (i=pos+1; i<Dsz; i++) {
      if ((x<D[i]) && (D[i]%x == 0)) {
        T -= T_mod(D[i], i, D, Dsz, DP);
        T %= M;
      }
    }
    T += (T<0?M:0);
    DP[pos] = T;
  } else {
    T = DP[pos];
  }
  return T;
}
int main()
{
  scanf("%d %d %d", &H, &W, &K);

  ll *H_D;
  ll *W_D;
  int H_Dsz;
  int W_Dsz;
  initD(H, &H_D, &H_Dsz);
  initD(W, &W_D, &W_Dsz);

  int i;
  ll *H_DP;
  ll *W_DP;
  H_DP = (ll*)malloc(sizeof(ll)*H_Dsz);
  W_DP = (ll*)malloc(sizeof(ll)*W_Dsz);
  for (i=0; i<H_Dsz; i++) H_DP[i] = 0;
  for (i=0; i<W_Dsz; i++) W_DP[i] = 0;

  int j;
  ll e,B,h,w;
  ll sum = 0;
  h = H;
  w = W;
  for (i=0; i<H_Dsz; i++) {
    for (j=0; j<W_Dsz; j++) {
      e = (w*h)/lcm(H/H_D[i],W/W_D[j]);
      B = pow_mod_K(K, e);
      B *= T_mod(H_D[i],i,H_D,H_Dsz,H_DP);
      B %= M;
      B *= T_mod(W_D[j],j,W_D,W_Dsz,W_DP);
      B %= M;
      sum += B;
      sum %= M;
    }
  }
  // フェルマーの小定理より
  // (W*H)^(-1)==(W*H)^(M-2) (mod M)
  printf("%lld\n", (sum*pow_mod(w*h,M-2))%M);
  return 0;
}
0