【Foreign】无聊的计算姬 [Lucas][BSGS]

无聊的计算姬

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

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

  

Source

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

  对于前50分:

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

  对于11~16的20分:

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

Code

  1 #include<iostream>
  2 #include<string>
  3 #include<algorithm>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cmath>
  8 #include<map>
  9 using namespace std;
 10 typedef long long s64;
 11
 12 const int ONE = 10000005;
 13
 14 map <int,int> f;
 15
 16 int T;
 17 int type,y,z,MOD;
 18 int Jc[ONE];
 19 int C[1005][1005];
 20
 21 int get()
 22 {
 23         int res=1,Q=1;  char c;
 24         while( (c=getchar())<48 || c>57)
 25         if(c==‘-‘)Q=-1;
 26         if(Q) res=c-48;
 27         while((c=getchar())>=48 && c<=57)
 28         res=res*10+c-48;
 29         return res*Q;
 30 }
 31
 32 int Quickpow(int a,int b,int MOD)
 33 {
 34         int res=1;
 35         while(b)
 36         {
 37             if(b&1) res=(s64)res*a%MOD;
 38             a=(s64)a*a%MOD;
 39             b>>=1;
 40         }
 41         return res;
 42 }
 43
 44 namespace PC
 45 {
 46         int Make_C(int a,int b,int MOD)
 47         {
 48             C[0][0]=1;
 49             for(int i=1;i<=a;i++)
 50             {
 51                 C[i][0]=1;
 52                 for(int j=1;j<=b;j++)
 53                 C[i][j] = (C[i-1][j]+C[i-1][j-1]) % MOD;
 54             }
 55             return C[a][b];
 56         }
 57
 58         int C(int n,int m,int MOD)
 59         {
 60             int up = Jc[n];
 61             int down = (s64)Jc[m] * Jc[n-m] % MOD;
 62             return (s64)up * Quickpow(down,MOD-2,MOD) % MOD;
 63         }
 64
 65         int Lucas(int n,int m,int MOD)
 66         {
 67             Jc[0]=1;
 68             for(int i=1;i<=MOD;i++) Jc[i] = (s64)Jc[i-1] * i % MOD;
 69             int res = 1;
 70             while(n && m)
 71             {
 72                 res = (s64)res * C(n%MOD,m%MOD,MOD) % MOD;
 73                 n/=MOD;    m/=MOD;
 74             }
 75             return res;
 76         }
 77 }
 78
 79 namespace PB
 80 {
 81         int Make_min(int a,int b,int MOD)
 82         {
 83             int res=1;
 84             if(res==b) return 0;
 85             f.clear();
 86             for(int i=1;i<=100000;i++)
 87             {
 88                 res = (s64)res * a % MOD;
 89                 if(f[res]) return -1;
 90                 f[res] = 1;
 91                 if(res==b) return i;
 92             }
 93             return -1;
 94         }
 95
 96         int BSGS(int A,int B,int MOD)
 97         {
 98             if(A % MOD == 0) return -1;
 99             int m = sqrt(MOD) + 1;
100             f.clear();
101             int record = B % MOD;
102             for(int i=1;i<=m;i++)
103             {
104                 record = (s64) record * A % MOD;
105                 f[record] = i;
106             }
107
108             int A_m = Quickpow(A,m,MOD);
109             record = 1;
110             for(int i=1;i<=m;i++)
111             {
112                 record = (s64)record * A_m % MOD;
113                 if(f[record])
114                 {
115                     int x = (i * m %MOD- f[record]+MOD) %MOD;
116                     return x;
117                 }
118             }
119             return -1;
120         }
121 }
122
123 int main()
124 {
125         T=get();
126         while(T--)
127         {
128             type=get();
129             y=get();    z=get();    MOD=get();
130             if(type==1) printf("%d\n",Quickpow(y,z,MOD));
131             if(type==3)
132             {
133                 if(z<=1000 && y<=1000)
134                     printf("%d\n",PC::Make_C(z,y,MOD));
135                 else
136                     printf("%d\n",PC::Lucas(z,y,MOD));
137             }
138             if(type==2)
139             {
140                 if(z<=1000 && y<=1000)
141                 {
142                     int res=PB::Make_min(y,z,MOD);
143                     if(res==-1) printf("Math Error\n");
144                     else printf("%d\n",res);
145                 }
146                 else
147                 {
148                     int res=PB::BSGS(y,z,MOD);
149                     if(res==-1) printf("Math Error\n");
150                     else printf("%d\n",res);
151                 }
152             }
153         }
154 }

时间: 2024-08-24 10:43:30

【Foreign】无聊的计算姬 [Lucas][BSGS]的相关文章

[BZOJ4765]普通计算姬

试题描述 "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些.普通计算机能计算数列区间和,而普通计算姬能计算树中子树和.更具体地,小G的计算姬可以解决这么个问题:给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和.计算姬支持下列两种操作: 1 给定两个整数u,v,修改点u的权值为v. 2 给定两个整数l,r,计算sum[l]+sum[l+1]+....+sum[r-1]

bzoj 4766: 文艺计算姬 -- 快速乘

4766: 文艺计算姬 Time Limit: 1 Sec  Memory Limit: 128 MB Description "奋战三星期,造台计算机".小W响应号召,花了三星期造了台文艺计算姬.文艺计算姬比普通计算机有更多的艺 术细胞.普通计算机能计算一个带标号完全图的生成树个数,而文艺计算姬能计算一个带标号完全二分图的生成树 个数.更具体地,给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图K_{n,m},计算姬能快 速算出其生成树个数.小W不知道计算姬算的对

BZOJ4766: 文艺计算姬

Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 737  Solved: 402[Submit][Status][Discuss] Description "奋战三星期,造台计算机".小W响应号召,花了三星期造了台文艺计算姬.文艺计算姬比普通计算机有更多的艺 术细胞.普通计算机能计算一个带标号完全图的生成树个数,而文艺计算姬能计算一个带标号完全二分图的生成树 个数.更具体地,给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二

NKOJ 费马小定理降幂 P3511无聊的计算

无聊的计算 [问题描述] nodgd 经常遇到很无聊的计算题,你看,这次又遇到了…… 这个题一开始给了 nodgd 两个序列??1, ??2, … , ????, ??1, ??2, … , ????.定义一个二 元函数??(??, ??) = ??,其中0 ≤ ?? < ??,且存在整数??使得?? = ?? + ????.现在,这道 题要计算满足条件?? ????? ????, ??? ≤ ??的有序数对(??,??)有多少个. [输入格式] 输入文件 A.in. 第一行两个整数??, ??

【bzoj4765】 普通计算姬

题意 给出一棵有根树,$n$个点每个都有一个点权.$m$组操作每次可以修改一个点权或者询问编号在区间$[l,r]$的点的子树权值和的和. Solution 我们对节点编号分块,每一块统计该块中的节点的子树权值和的和.dfs处理出修改一个节点,需要对应修改它的祖先和它的所在的哪些块.另外再开一个树状数组,树状数组中每一个元素是对应dfs的点的权值,这样我们可以求出任意子树的权值和. 对于询问,在中间的块直接统计.两侧零散的块在树状数组上暴力查询子树权值和.所以令块的大小$S=\sqrt{n/\lo

【bzoj4765】普通计算姬(双重分块)

题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4765 这道题已经攒了半年多了...因为懒,一直没去写...所以今天才把这道题写出来... 如果是要维护区间权值和.子树权值和,都可以用线段树/树状数组轻松解决.但是这道题要维护的是子树权值和的区间和,这就比较难搞了. 当需要维护一些看起来很难直接维护的信息时,我们一般会想到分块.于是考虑这样的分块:按编号把每√n个节点划分为一块,维护每一块所有节点的sum值的和,然后再维护每个节点的s

总结与心得(持续更新)

不知道为什么,刚学的算法过了2个月就忘得一干二净,我并没有背代码啊,当时学的时候还刷了好多题来着→_→,我是不是大脑能力严重衰退了. 动态规划 单调队列 一般情况下,${dp}$方程可以搞成这样:${f_i=f_j+t_j+t_i}$,只要其中没有变量同时与${i,j}$都有关,那么我们可以用单调队列来做,单调队列里面元素的关键字就是与${j}$有关的东西${f_j+t_j}$.example:生产产品 有些比较特殊的,虽然存在同时与${i,j}$相关的函数,但是这个函数比较简单,使得已经存在在

写个百万级别full-stack小型协程库——原理介绍

其实说什么百万千万级别都是虚的,下面给出实现原理和测试结果,原理很简单,我就不上图了: 原理:为了简单明了,只支持单线程,每个协程共享一个4K的空间(你可以用堆,用匿名内存映射或者直接开个数组也都是可以的,总之得保证4K页对齐的空间),每个协程自己有私有栈空间指针privatestackptr,每个时刻只有一个协程在运行,此时栈空间在这个4K共享空间中(当然除了main以外),当切换协程时,动态分配一个堆内存,大小为此时协程栈实际大小(一般都很小,小的只有几十个Bytes, 大的有几百个Byte

[BZOJ]2017省队十连测推广赛1

听学长说有比赛就随便打一打. A.普通计算姬 题目大意:给出一棵带权树,支持一下两种操作:1.修改一个点的权值:2.给出l,r,询问以点l为根的子树和.点l+1为根的子树和.点l+2为根的子树和--点r为根的子树和的总和.(点数.操作数不超过10^5) 思路:感觉是三题中最难的.给出的[l,r]区间在树上没有实际意义,不好利用数据结构维护.考虑若不修改,可以一遍dfs算出每个点对应的dfs序,这样每棵子树都对应一个dfs序的区间,前缀和一下就能O(1)查子树和,再按点的编号顺序把子树和前缀和一下