无聊的计算姬

Time Limit: 10 Sec Memory Limit: 256 MB

Description

img

Input

img

Output

img

Sample Input

6
  2 2 3 4
  3 2 7 9
  2 1 2 9
  3 1 6 7
  1 5 3 7
  1 9 2 8

Sample Output

Math Error
  3
  Math Error
  6
  6
  1

HINT

img

Solution

我们可以分步骗分。(Task1直接快速幂即可。)

对于前50分:

对于Task2,我们直接暴力枚举,出现一个重复的停止,判断是否存在即可,对于Task3,直接n^2递推组合数即可。

对于11~16的20分:

对于Task2,我们运用BSGS求解即可,对于Task3,直接上Lucas即可。

BearChild不会做满分,满分要运用exBSGS以及exLucas&&CRT。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include<bits/stdc++.h>
using namespace std;
typedef long long s64;

const int ONE = 10000005;

map <int,int> f;

int T;
int type,y,z,MOD;
int Jc[ONE];
int C[1005][1005];

int get()
{
int res=1,Q=1; char c;
while( (c=getchar())<48 || c>57)
if(c=='-')Q=-1;
if(Q) res=c-48;
while((c=getchar())>=48 && c<=57)
res=res*10+c-48;
return res*Q;
}

int Quickpow(int a,int b,int MOD)
{
int res=1;
while(b)
{
if(b&1) res=(s64)res*a%MOD;
a=(s64)a*a%MOD;
b>>=1;
}
return res;
}

namespace PC
{
int Make_C(int a,int b,int MOD)
{
C[0][0]=1;
for(int i=1;i<=a;i++)
{
C[i][0]=1;
for(int j=1;j<=b;j++)
C[i][j] = (C[i-1][j]+C[i-1][j-1]) % MOD;
}
return C[a][b];
}

int C(int n,int m,int MOD)
{
int up = Jc[n];
int down = (s64)Jc[m] * Jc[n-m] % MOD;
return (s64)up * Quickpow(down,MOD-2,MOD) % MOD;
}

int Lucas(int n,int m,int MOD)
{
Jc[0]=1;
for(int i=1;i<=MOD;i++) Jc[i] = (s64)Jc[i-1] * i % MOD;
int res = 1;
while(n && m)
{
res = (s64)res * C(n%MOD,m%MOD,MOD) % MOD;
n/=MOD; m/=MOD;
}
return res;
}
}

namespace PB
{
int Make_min(int a,int b,int MOD)
{
int res=1;
if(res==b) return 0;
f.clear();
for(int i=1;i<=100000;i++)
{
res = (s64)res * a % MOD;
if(f[res]) return -1;
f[res] = 1;
if(res==b) return i;
}
return -1;
}

int BSGS(int A,int B,int MOD)
{
if(A % MOD == 0) return -1;
int m = sqrt(MOD) + 1;
f.clear();
int record = B % MOD;
for(int i=1;i<=m;i++)
{
record = (s64) record * A % MOD;
f[record] = i;
}

int A_m = Quickpow(A,m,MOD);
record = 1;
for(int i=1;i<=m;i++)
{
record = (s64)record * A_m % MOD;
if(f[record])
{
int x = (i * m %MOD- f[record]+MOD) %MOD;
return x;
}
}
return -1;
}
}

int main()
{
T=get();
while(T--)
{
type=get();
y=get(); z=get(); MOD=get();
if(type==1) printf("%d\n",Quickpow(y,z,MOD));
if(type==3)
{
if(z<=1000 && y<=1000)
printf("%d\n",PC::Make_C(z,y,MOD));
else
printf("%d\n",PC::Lucas(z,y,MOD));
}
if(type==2)
{
if(z<=1000 && y<=1000)
{
int res=PB::Make_min(y,z,MOD);
if(res==-1) printf("Math Error\n");
else printf("%d\n",res);
}
else
{
int res=PB::BSGS(y,z,MOD);
if(res==-1) printf("Math Error\n");
else printf("%d\n",res);
}
}
}
}