• 牛客编程巅峰赛S1第12场 王者C-椭圆曲线(快速乘的运用)


    题目链接:https://ac.nowcoder.com/acm/contest/6916/C
    CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/108035320

    题目描述
    椭圆曲线加密算法是在椭圆曲线有限域上进行加密的算法,一般的椭圆曲线为(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)(P(x_1,x_2),Q(x_2,y_2),R(x_3,y_3)),其中R=P+Q,有
    (x_3equiv k^2-x_1-x_2: (mod: p))
    (y_3equiv k(x_1-x_3)-y_1: (mod: p))
    若P=Q,则(k=frac{3x_1^2+a}{2y_1}: (mod: p))
    (P eq 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)

    备注:
    (0leq x_1,y_1leq 10^9)(1leq nleq 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);
        }
    };
    
  • 相关阅读:
    图解iPhone开发新手教程
    究竟什么是关系数据库?
    【设计模式】模板方法模式
    SoftReference
    OpenCV在ARM上的移植
    Luci流程分析(openwrt下)
    delete
    delete
    浅析busybox-1.12.0中ash的脚本命令局限性
    shell总结:读取文件、参数、if、分割字符串、数组长度、空文件、变量赋值、多进程、按行切割文件、查看线程
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13512283.html
Copyright © 2020-2023  润新知