BZOJ2242 [SDOI2011]計算器 快速冪+Exgcd+離散對數 數學專題第十題
題目p2109
From Tyvj Guest☆【bzoj2242】計算器
背景 Background
此係列問題為數論專題
具體參考博文
http://blog.csdn.net/chty2018/article/details/53432272
描述 Description
你被要求設計一個計算器完成以下三項任務:
1、給定y,z,p,計算Y^Z Mod P 的值;
2、給定y,z,p,計算滿足xy≡ Z ( mod P )的最小非負整數;
3、給定y,z,p,計算滿足Y^x ≡ Z ( mod P)的最小非負整數。
輸入格式 Input Format
輸入包含多組資料。
第一行包含兩個正整數T,K分別表示資料組數和詢問型別(對於一個測試點內的所有資料,詢問型別相同)。
以下行每行包含三個正整數y,z,p,描述一個詢問。
輸出格式 Output Format
對於每個詢問,輸出一行答案。對於詢問型別2和3,如果不存在滿足條件的,則輸出“Orz, I cannot find x!”,注意逗號與“I”之間有一個空格。
樣例輸入 Sample Input
樣例輸入1】
3 1
2 1 3
2 2 3
2 3 3
【樣例輸入2】
3 2
2 1 3
2 2 3
2 3 3
【樣例輸入3】
4 3
2 1 3
2 2 3
2 3 3
2 4 3
樣例輸出 Sample Output
【樣例輸出1】
2
1
2
【樣例輸出2】
2
1
0
【樣例輸出3】
0
1
Orz, I cannot find x!
0
時間限制 Time Limitation
1s
註釋 Hint
【資料規模和約定】
對於20%的資料,K=1;
對於35%的資料,K=2;
對於45%的資料,K=3;
對於100%的資料,1≤y,z,P≤〖10〗^9,P為質數,1≤T≤10。
來源 Source
【bzoj2242】計算器
題面,資料來自宋逸群
題解
第一問快速冪
第二問exgcd
第三問BSGS,好麻煩我就先略
為啥叫baby step giant step,我其實不是很懂
卓神說這是meet in the middle的一種運用
求設
用費馬小定理顯然可得設其為
把
放入hash或者map
然後列舉k,查詢
顯然取複雜度比較優秀。。
轉自hzwer
然而我現在還是不會離散對數。
程式碼
這個學習黃學長的程式碼的評測結果:
Result | Memory | Time | Language | Code_Length | Submit_Time |
---|---|---|---|---|---|
Accepted | 3288 kb | 2012 ms | C++/Edit | 2158 B | 2019-01-18 16:23:49 |
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
int f=1,x=0;
char ch=getchar();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
return x*f;
}
/////////////////////////////////////////////////////////////////////////////
//快速冪
int solve1(ll y,int z,int p)
{
y%=p;
ll ans=1;
for (int i=z; i; i>>=1,y=y*y%p)
if (i&1)
ans=ans*y%p;
return ans;
}
/////////////////////////////////////////////////////////////////////////////
//Exgcd
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
void exgcd(int a,int b,int &x,int &y)
{
if (!b)
{
x=1,y=0;
return;
}
exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
}
void solve2(int y,int z,int p)
{
p=-p;
int t=gcd(y,p);
if (z%t)
{
puts("Orz, I cannot find x!");
return ;
}
y/=t,z/=t,p/=t;
int a,b;
exgcd(y,p,a,b);
a=(ll)a*z%p;
while (a<0) a+=p;
printf("%d\n",a);
}
/////////////////////////////////////////////////////////////////////////////
//離散對數
map<int,int>mp;
void solve3(int y,int z,int p)
{
y%=p;
if (!y && !z)
{
puts("1");
return ;
}
if (!y)
{
puts("Orz, I cannot find x!");
return ;
}
mp.clear();
ll m=ceil(sqrt(p)),t=1;
mp[1]=m+1;
for (ll i=1; i<m; ++i)
{
t=t*y%p;
if (!mp[t])
mp[t]=i;
}
ll tmp=solve1(y,p-m-1,p),inv=1;
for (ll k=0; k<m; ++k)
{
int i=mp[z*inv%p];
if (i)
{
if (i==m+1) i=0;
printf("%lld\n",k*m+i);
return;
}
inv=inv*tmp%p;
}
puts("Orz, I cannot find x!");
}
/////////////////////////////////////////////////////////////////////////////
int main()
{
int T=read(),K=read();
while (T--)
{
int y=read(),z=read(),p=read();
if (K==1)
printf("%d\n",solve1(y,z,p));
else if (K==2)
solve2(y,z,p);
else
solve3(y,z,p);
}
return 0;
}
下面的程式碼轉自大神yyb
Result | Memory | Time | Language | Code_Length | Submit_Time |
---|---|---|---|---|---|
Accepted | 13408 kb | 152 ms | C++/Edit | 2297 B | 2019-01-18 14:41:52 |
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
const int HashMod=100007;
inline int read() {
RG int x=0,t=1;
RG char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') t=-1,ch=getchar();
while (ch<='9'&&ch>='0') x=x*10+ch-48,ch=getchar();
return x*t;
}
int fpow(int a,int b,int MOD) {
int s=1;
while (b) {
if (b&1)
s=1ll*s*a%MOD;
a=1ll*a*a%MOD;
b>>=1;
}
return s;
}
void NoAnswer() {
puts("Orz, I cannot find x!");
}
namespace Task1 {
void Solve(int y,int z,int p) {
printf("%d\n",fpow(y,z,p));
}
}
namespace Task2 {
void Solve(int y,int z,int p) {
if (y%p==0&&z%p)
NoAnswer();
else
printf("%lld\n",1ll*fpow(y,p-2,p)*z%p);
}
}
namespace Task3 {
struct HashTable {
struct Line {
int u,v,next;
} e[1000000];
int h[HashMod],cnt;
void Add(int u,int v,int w) {
e[++cnt]=(Line) {
w,v,h[u]
};
h[u]=cnt;
}
void Clear() {
memset(h,0,sizeof(h));
cnt=0;
}
void Hash(int x,int k) {
int s=x%HashMod;
Add(s,k,x);
}
int Query(int x) {
int s=x%HashMod;
for (int i=h[s]; i; i=e[i].next)
if (e[i].u==x)
return e[i].v;
return -1;
}
} Hash;
void Solve(int y,int z,int p) {
if (y%p==0) {
NoAnswer();
return;
}
y%=p;
z%=p;
if (z==1) {
puts("0");
return;
}
int m=sqrt(p)+1;
Hash.Clear();
for (RG int i=0,t=z; i<m; ++i,t=1ll*t*y%p)
Hash.Hash(t,i);
for (RG int i=1,tt=fpow(y,m,p),t=tt; i<=m+1; ++i,t=1ll*t*tt%p) {
int k=Hash.Query(t);
if (k==-1) continue;
printf("%d\n",i*m-k);
return;
}
NoAnswer();
}
}
int main() {
int T=read(),K=read();
while(T--) {
int y=read(),z=read(),p=read();
if (K==1) Task1::Solve(y,z,p);
if (K==2) Task2::Solve(y,z,p);
if (K==3) Task3::Solve(y,z,p);
}
return 0;
}
相關文章
- 計算機基礎:離散數學和完備性計算機
- 離散數學(數論基礎)
- 離散數學——3.命題邏輯的等值演算
- 離散數學——6.命題邏輯的應用
- 離散數學——5.命題邏輯的推理理論
- 專題:數學
- 離散數學——4.命題邏輯公式的正規化公式
- 離散數學——2.命題邏輯公式語法和語義公式
- 離散數學及其應用 (第2版)
- [SDOI2011]計算器
- 當程式設計師面對小學數學題程式設計師
- 數學專業的數學與計算機專業的數學的比較計算機
- 小學數學程式設計題程式設計
- 一些關係(離散數學中的)的程式設計思想程式設計
- ACM演算法——數學專題ACM演算法
- 離散數學 II(最全面的知識點彙總)
- (翻譯)2016美國數學建模MCM B題(離散型)翻譯:Space Junk太空垃圾
- 【離散優化】覆蓋問題優化
- iOS數學題iOS
- 計算水仙花數運算超時問題
- 一個浮點數計算的問題
- 【演算法學習】數學專題 有理數類别範本演算法
- c# winform之小型數學計算器C#ORM
- [每日一題] 第十六題:n個骰子的點數每日一題
- 數對數目;及LIS問題分析
- python計算對數值Python
- 刷題系列 - 計算爬樓梯不同步數的方法數
- JavaScript解決浮點數算數運算精度問題JavaScript
- javascript浮點數計算精度問題介紹JavaScript
- 離散數學實踐作業,java輸出真值表(轉)Java
- LightOJ 1070 Algebraic Problem:矩陣快速冪 + 數學推導AI矩陣
- 費馬小定理 + 費馬大定理 + 勾股數的求解 + 快速冪 + 矩陣快速冪 【模板】矩陣
- 結對專案-增強型科學計算器
- 例項複習機器學習數學 - 2. 幾種典型離散隨機變數分佈機器學習隨機變數
- zzulioj1893: 985的數學難題(二進位制計算)
- linux 快速計算檔案數和目錄數 (轉)Linux
- 計數題總結
- 集合冪級數學習筆記筆記