日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

N次剩余(详解+例题+代码)

發(fā)布時(shí)間:2024/8/23 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 N次剩余(详解+例题+代码) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
從《國(guó)際大學(xué)生程序設(shè)計(jì)大賽算法與實(shí)現(xiàn)》中所學(xué)
任務(wù):
給定N, a, p, 求出(x^N)%p=a 在模p意義下的所有解x。
說明:
令g為p的原根,因?yàn)閜為素?cái)?shù),所以phi(p)=p-1。
由原根的性質(zhì)得:
如果g為p的原根,則:g^i mod p != g^j mod p (p為素?cái)?shù)), 其中i != j且i, j介於1至(p-1)之間
所以,可以設(shè)g^y=x, g^t=a,則有:
g^(y*N)%p=g^t
又由原根的性質(zhì):
g^(y*N)%p=g^t -> (y*N)%(p-1)=t (此方程可以由拓展歐幾里得解)
另外g^t=a可以由離散對(duì)數(shù)求出
給定newx, k, m, 方程 (x^k)%m=newx, 求在模m意義下的所有解x。
限制:
0 <= newx, m, k <= 1.5*10^15; m是素?cái)?shù)。
/*hdu 3930題意:給定newx, k, m, 方程 (x^k)%m=newx, 求在模m意義下的所有解x。限制:0 <= newx, m, k <= 1.5*10^15; m是素?cái)?shù)。思路:N次剩余*/ #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <vector> #include <algorithm> using namespace std; #define LL __int64 #define PB push_back LL mul(LL a,LL b,LL m){LL ret = 0;a %= m;while(b){if(b & 1) ret = (ret + a) % m;a = (a + a) % m;b >>= 1;}return ret; } LL a_b_MOD_c(LL a,LL b,LL m){LL ret = 1;a %= m;while(b){if(b&1) ret = mul(ret,a,m);a = mul(a,a,m);b >>= 1;}return ret; }LL ext_gcd(LL a,LL b,LL &x,LL &y){if(b==0) { x=1, y=0; return a; }LL ret= ext_gcd(b,a%b,y,x);y-= a/b*x;return ret; } vector<LL> a; bool g_test(LL g,LL p){for(LL i=0;i<a.size();++i)if(a_b_MOD_c(g,(p-1)/a[i],p)==1)return 0;return 1; } LL pri_root(LL p){a.clear();LL tmp=p-1;for(LL i=2;i<=tmp/i;++i)if(tmp%i==0){a.push_back(i);while(tmp%i==0)tmp/=i;}if(tmp!=1)a.push_back(tmp);LL g=1;while(true){if(g_test(g,p))return g;++g;} } const int HASH_MOD=9876543; LL key[HASH_MOD], val[HASH_MOD]; int head[HASH_MOD], next[HASH_MOD]; struct Hash{int tot;void init(){memset(head, -1, sizeof(head));tot = 0;}LL insert(LL x, LL y){int k = x % HASH_MOD;key[tot] = x;val[tot] = y;next[tot] = head[k];head[k] = tot++;}LL find(LL x){int k = x % HASH_MOD;for(int i = head[k]; i != -1; i = next[i])if(key[i] == x)return val[i];return -1;} }hs; //求解模方程a^x=b(mod m),n為素?cái)?shù),無解返回-1 //注意:要求0 < a < m; 0 <= b < m; 否則按題意自己轉(zhuǎn)化。 //復(fù)雜度O(sqrt(m)) LL log_mod(LL a, LL b, LL m){hs.init();LL s = ceil(sqrt(m + 0.5));LL cur = 1;for (int i = 0; i < s; ++i){if(hs.find(cur)==-1) hs.insert(cur,i); //記得先判重,在插入cur = cur * a % m;}LL v = a_b_MOD_c(a, (m - s - 1 + m) % m, m);for(int i = 0; i < s; ++i){LL tmp = hs.find(b);if(tmp!=-1)return s * i + tmp;b=b*v%m;}return -1; } /*n次剩余任務(wù):給定N, a, p, 求出(x^N)%p=a 在模p意義下的所有解x。說明:令g為p的原根,因?yàn)閜為素?cái)?shù),所以phi(p)=p-1。由原根的性質(zhì)得:如果g為p的原根,則:g^i mod p != g^j mod p (p為素?cái)?shù)), 其中i != j且i, j介於1至(p-1)之間所以,可以設(shè)g^y=x, g^t=a,則有:g^(y*N)%p=g^t又由原根的性質(zhì):g^(y*N)%p=g^t -> (y*N)%(p-1)=t (此方程可以由拓展歐幾里得解)另外g^t=a可以由離散對(duì)數(shù)求出*/ vector<LL> residue(LL p, LL N, LL a){LL g = pri_root(p);g %= p;LL m = log_mod(g, a, p);vector<LL> ret;if(a == 0){ret.PB(0);return ret;}if(m == -1)return ret;LL A = N, B = p - 1, C = m, x, y;LL d = ext_gcd(A, B, x, y);if(C % d != 0) return ret;x = x * (C / d) % B;LL delta = B / d;for(int i = 0; i < d; ++i){x = ((x + delta) % B + B) % B;ret.PB(a_b_MOD_c(g, x, p));}sort(ret.begin(), ret.end());ret.erase(unique(ret.begin(), ret.end()), ret.end());return ret; } int main(){int cas = 0;LL k,m,newx;while(scanf("%I64d%I64d%I64d",&k, &m, &newx)!=EOF){vector<LL> ans;ans = residue(m,k,newx);printf("case%d:\n",++cas);if(ans.size()==0) puts("-1");for(int i = 0; i < ans.size(); ++i)printf("%I64d\n",ans[i]);}return 0; }

總結(jié)

以上是生活随笔為你收集整理的N次剩余(详解+例题+代码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。