http://acm.fzu.edu.cn/problem.php?pid=1905

         浙江理工邀请赛G题的进化版,AC大牛出的题,专门卡矩阵做法的,不用AC大牛的做法至今无人能过,比赛的时候想起来AC大牛的blog中有写过解法的,跑去AC大牛blog一看,已经被删除啦。。。唉,怪自己当初没有好好研究AC牛的解法,想会矩阵解法就万事大吉了。AC牛的解法效率相当高。。。
         这是AC大牛的解法传送门  http://hi.baidu.com/aekdycoin/blog/item/63f633ec11c822d8b21cb168.html  OrzOrz

         以下是我的代码,基本是模仿AC牛的代码写的,主要是因为之前phi函数写次了,TLE 好多次,就按照AC的代码在改,改到最后代码基本一样了,我还是TLE。。。后来发现是phi函数写次了。。。现在的代码基本跟AC的一样。。。我觉得AC大牛的那个sum函数写得很好

  1// AC大牛的博文 http://hi.baidu.com/aekdycoin/blog/item/63f633ec11c822d8b21cb168.html
  2// n - spos 不一定是 Slen 的整数倍,而我们需要的是
  3// (n - Spos) / Slen  的向下取整的结果(  完整周期数)
  4// (n - Spos) % Slen = C 表示最后剩余的那个不完整周期
  5
  6// 而由于周期数很大,因此我们只需要计算 周期数  mod P
  7// 那么可以这么转化
  8// ( n - Spos - C ) / Slen % P -> ( n - Spos - C ) % ( P * Slen ) / Slen
  9
 10#include <stdio.h>
 11#include <iostream>
 12using namespace std;
 13
 14typedef __int64 ll;
 15ll Spos, Slen;
 16ll X1, Y1, Y2, Z2;
 17ll HP, P, Q;
 18
 19template<class T> T MOD( T a, T b ){ a %= b; return a < 0 ? a + b : a; }
 20
 21ll phi( ll n )
 22{
 23    ll ret = n;
 24    int i, j;
 25    for( i = 2, j = 4; j <= n; i++, j += i + i - 1 )
 26    {
 27        if!( n % i ) )
 28        {
 29            ret = ret / i * ( i - 1 );
 30            while!( n % i ) ) n /= i;
 31        }

 32    }

 33    if( n > 1 ) ret = ret / n * ( n - 1 );
 34    return ret;
 35}

 36
 37ll pow_mod( ll a, ll b, ll c )
 38{
 39    ll ans = 1, d = a % c;
 40    while( b )
 41    {
 42        if( b & 1 ) ans = d * ans % c;
 43        d = d * d % c;
 44        b >>= 1;
 45    }

 46    return ans;
 47}

 48
 49ll mul_mod( ll a, ll b, ll c )
 50{
 51    ll ans = 0, d = a % c;
 52    while( b )
 53    {
 54        if( b & 1 )if( ( ans += d ) >= c ) ans -= c;
 55        if( ( d <<= 1 ) >= c ) d -= c;
 56        b >>= 1;
 57    }

 58    return ans ;
 59}

 60
 61ll Bpow_mod( ll a, ll b, ll c )
 62{
 63    ll ans = 1, d = a % c;
 64    while( b )
 65    {
 66        if( b & 1 ) ans = mul_mod( ans, d, c );
 67        d = mul_mod( d, d, c );
 68        b >>= 1;
 69    }

 70    return ans;
 71}

 72
 73// 计算 1 + Q + Q^2 + Q^3 +  + Q^n;
 74ll sum( ll n )
 75{
 76    ll S;
 77    if( n < 0 ) return 0;
 78    if( n == 0 ) return 1 % P;
 79    if( n == 1 ) return ( 1 + Q ) % P;
 80    if( n & 1 )
 81    {
 82        S = sum( n >> 1 );
 83        return ( S + S * pow_mod( Q, n / 2 + 1, P ) % P ) % P;
 84    }

 85    S = sum( n - 1 );
 86    return ( S + pow_mod( Q, n, P ) ) % P;
 87}

 88
 89void Read( )
 90{
 91    scanf("%I64d%I64d",&X1,&Y1);
 92    scanf("%I64d%I64d%I64d",&Y2,&Z2,&P);
 93}

 94
 95// ( n - Spos - C ) / Slen % P -> ( n - Spos - C ) % ( P * Slen ) / Slen
 96//  Spos总归会是一个比较小的数
 97ll cal( ll & res_seg )  // res_seg 为 C 
 98{
 99    ll mod_res = pow_mod( Y2, Z2, Slen );
100    res_seg = mod_res = MOD( mod_res - Spos, Slen );
101    ll ret = Bpow_mod( Y2, Z2, HP ) - Spos - mod_res;
102    ret = MOD( ret, HP ) / Slen;
103    return ret; // 返回周期数 mod P之后的余数
104}

105
106void solve( int k )
107
108    int i;
109    ll ret, ss, v, limit, XX; 
110    Slen = phi( P );
111    HP = (ll)P * Slen;
112    Q = pow_mod( X1, Y1, P );
113    Q = MOD( -Q, P );
114    for( Spos = 0;  ; Spos++ )
115        if( pow_mod( Q, Spos, P ) == pow_mod( Q, Spos + Slen, P ) )break;
116    XX = 1;
117    for( i = 0; i < Y1; i++ )
118    {
119        XX *= X1;
120        if( XX > Spos )
121            break;
122    }

123    if( i == Y1 )
124    {
125        limit = XX;
126        for( ret = 0, v = 1 % P, i = 0; i < limit; v = v * Q % P, i++ )
127            ret = ( ret + v ) % P;
128        printf("Case #%d: %I64d\n",k, ret);
129        return ;
130    }

131    limit = Spos;
132    // 计算不再循环周期之内的数之和 mod P
133    for( ret = 0, v = 1 % P, i = 0; i < limit; v = v * Q % P, i++ )
134        ret = ( ret + v ) % P;
135    // 计算一个周期内的数之和 mod P
136    ll seg_sum = sum( Slen - 1 ) * pow_mod( Q, Spos, P ) % P;
137    ll res_seg;
138    ss = cal( res_seg );
139    ret = ( ret + seg_sum * ss % P ) % P;
140    ret = ( ret + sum( res_seg - 1 ) * pow_mod( Q, Spos, P ) % P ) % P;
141    printf("Case #%d: %I64d\n",k,ret);
142}

143
144int main( int argc, char *argv[] )
145{
146    int t, k = 1;
147    scanf("%d",&t);
148    while( t-- )
149    {
150        Read( );
151        solve( k );
152        k++;
153    }

154    return 0;
155}

156