牛客程式設計巔峰賽S1第12場 王者C-橢圓曲線(快速乘的運用)
阿新 • • 發佈:2020-08-16
題目連結:https://ac.nowcoder.com/acm/contest/6916/C
CSDN食用連結:
題目描述
橢圓曲線加密演算法是在橢圓曲線有限域上進行加密的演算法,一般的橢圓曲線為\(E_{p}(a,b): y^2=x^3+ax+b\),其中p為質數。
橢圓曲線上的點的運算滿足以下規則:
1.曲線上A、B不同兩點相加,過A、B兩點畫一條直線,找到直線與橢圓曲線的交點,交點關於x軸對稱位置的點,定義為A+B,即為加法。如下圖所示:A + B = C
2.相同點A與A相加,過A點做切線,與橢圓曲線的交點,交點關於x軸對稱位置的點,定義為A + A,即2A,即為二倍運算。
\(E_{p}(a,b): y^2=x^3+ax+b\)
\(x_3\equiv k^2-x_1-x_2\: (mod\: p)\)
\(y_3\equiv k(x_1-x_3)-y_1\: (mod\: p)\)
若P=Q,則\(k=\frac{3x_1^2+a}{2y_1}\: (mod\: p)\)
若\(P\neq Q\),則\(k=\frac{y_2-y_1}{x_2-x_1}\: (mod\: p)\)
現有\(E_p(1,1)\),其中p=1000000007,牛牛得到了點\(P(x_1,y_1)\),你能告訴她\(\ nP\)是多少嗎。
輸入
(0,1),3
輸出
(72,611)
備註:
\(0\leq x_1,y_1\leq 10^9\),\(1\leq n\leq 10^9\)
題目的意思是讓你求\(P+P+P+P+...+P\)的值,而這些運算可以通過上面的公式得到,只不過有點傷人的是,n的範圍在\(1e9\),所以我們不能直接暴力地一個一個加,那麼我們可以想到快速乘(實際上本質是個加法運算),這個東西就很方便了。。。只不過它滿不滿足快速乘就不太清楚了,只不過可以衝一波。然後就愉快地發現。。。A了。
以下是AC程式碼:
/** * struct Point { * int x; * int y; * }; */ typedef long long ll; const int mod=1e9+7; class Solution { public: /** * * @param P Point類 * @param n int整型 * @return Point類 */ ll qpow(ll a,ll b){ ll ans=1; a%=mod; while (b){ if (b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } ll pw(ll x) {return x*x%mod;} Point Plus(Point a,Point b) { ll x1=a.x,x2=b.x,y1=a.y,y2=b.y; if (x1==x2 && y1==y2){ ll k=(3LL*pw(x1)+1)%mod*qpow(2LL*y1,mod-2)%mod; int x3=(pw(k)-((x1+x2)%mod)+mod)%mod; int y3=(k*(x1-x3+mod)%mod-y1+mod)%mod; return Point{x3,y3}; } else { ll k=(y2-y1+mod)%mod*qpow((x2-x1+mod),mod-2)%mod; int x3=(pw(k)-((x1+x2)%mod)+mod)%mod; int y3=(k*(x1-x3+mod)%mod-y1+mod)%mod; return Point{x3,y3}; } } Point multi(Point a,int b) { Point ans=a; b--; while (b){ if (b&1) ans=Plus(ans,a); a=Plus(a,a); b>>=1; } return ans; } Point NTimesPoint(Point P, int n) { return multi(P,n); } };