【SDOI2013】随机数生成器

Source and Judge

SDOI2013
Luogu3306
Bzoj3122

Record

2h

Analysis

请先思考后再展开

随便推推柿子,发现有通项公式
$x_i=a^{i-1}x_1 + b(1+a+a^2…+a^{i-2}) (\mod p)$
$x_i=a^{i-1}x_1 + b \times (a^{i-1}-1) \times inv(a-1) (\mod p)$
注意0没有逆元,所以要特判a=1的情况,即一个带模等差数列,解一个同余方程即可
而对于普遍情况,可以BSGS,而且不用拓展,因为已经保证p是素数,而且a小于p

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
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<map>
#include<set>
#include<queue>
#include<deque>
#include<vector>
#include<bitset>
#include<algorithm>
using namespace std;
namespace mine
{
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
int mymax(int x,int y) {return x>y?x:y;}
int mymin(int x,int y) {return x<y?x:y;}
int myabs(int x) {return x>0?x:-x;}
const int MAXN=610000;
ll Mod;
ll gcd(ll a,ll b) {return (b==0)?a:gcd(b,a%b);}
ll qpower(ll a,ll e)
{
ll ans=1;
while(e>0)
{
if(e&1) ans=(ans*a)%Mod;
a=(a*a)%Mod;e>>=1;
}
return ans;
}
ll inv(ll x) {return qpower(x,Mod-2);}
map<ll,int> hash;
int BSGS(ll a,ll b)
{
hash.clear();//debug
ll m=ceil(sqrt( (double)Mod ));
ll t=a,now=1;
for(int j=0;j<=m;j++) hash[ b*now%Mod ]=j,now=now*t%Mod;
t=qpower(a,m),now=t;
for(int i=1;i<=m;i++)
{
if(hash.count(now)) return (i*m-hash[now])+1;
now=now*t%Mod;
}
return -1;
}
void main()
{
int T;scanf("%d",&T);
while(T--)
{
ll a,b,st,ed;scanf("%lld%lld%lld%lld%lld",&Mod,&a,&b,&st,&ed);
if(st==ed) {puts("1");continue;}//debug 柿子要求天数>1
if(a==0) {puts( (b==ed)?"2":"-1" );continue;}//debug
if(a==1)//debug 相当于除以0
{
if(b==0) puts("-1");
else
{
//st+b*x=ed (mod Mod)
ll ans=((ed-st)%Mod+Mod)%Mod;
printf("%lld\n",ans*inv(b)%Mod+1);
}
continue;
}
//if( gcd(st+b*inv(a-1),Mod)!=1 ) {puts("-1");continue;}
//debug st+b*inv(a-1)这个柿子,本来想着要丢到逆元里面,所以不能%
//但其实,一是应该在除过去之前就被%,二是它可能比Mod大
int ans=BSGS(a,(ed+b*inv(a-1)%Mod)*inv(st+b*inv(a-1)%Mod)%Mod);
printf("%d\n",ans);
}
}
};
int main()
{
mine::main();
}

本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布
本文地址:http://zory.cf/posts/41a1.html
转载请注明出处,谢谢!

哪怕是一杯奶茶,也将鼓励我继续创作!
0%