zoukankan      html  css  js  c++  java
  • 随机乱搞算法

    模拟退火

    bzoj3680 吊打XXX

    题目大意:给定一些绳子和绳子上的重量,求出最后绳结的坐标。

    思路:这个位置就是广义费马点,就是所有点到这个点的距离*每个点的权值最小的点。模拟退火,各种调常数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #define maxnode 10005
    using namespace std;
    struct use{
        double x,y,gi;
    }ai[maxnode]={0},ans;
    double minn=999999999999999LL;
    int n;
    double ran(){return rand()%1000/1000.0;}
    double fang(double a){return a*a;}
    double dis(use a,use b){return sqrt(fang(a.x-b.x)+fang(a.y-b.y));}
    double calc(use a)
    {
        int i;double j=0;
        for (i=1;i<=n;++i) j+=dis(a,ai[i])*ai[i].gi;
        if (j<minn){minn=j;ans=a;} return j;
    }
    void work(double t)
    {
        use a,now=ans;int i;double j;
        while(t>0.01)
        {
            a.x=now.x+t*(ran()*2-1);
            a.y=now.y+t*(ran()*2-1);
            j=calc(now)-calc(a);
            if (j>0||exp(j/t)>ran()) now=a;
            t*=0.980;
        }
        for (i=1;i<=1000;++i)
        {
            a.x=ans.x+t*(ran()*2-1);
            a.y=ans.y+t*(ran()*2-1);
            calc(a);
        }
    }
    int main()
    {
        int i,j;scanf("%d",&n);srand(23333);
        for (i=1;i<=n;++i)
        {
            scanf("%lf%lf%lf",&ai[i].x,&ai[i].y,&ai[i].gi);
            ans.x+=ai[i].x*1.0;ans.y+=ai[i].y*1.0;
        }ans.x/=n;ans.y/=n;
        work(500000);printf("%.3f %.3f
    ",ans.x,ans.y);
    }
    View Code

    随机增量

    bzoj2823 信号塔

    题目大意:给定一些点,求最小的覆盖所有点的圆。

    思路:假定当前的圆是ans,穷举所有点,如果某个点i不能被覆盖,就把当前点设为圆心、半径为0;然后找之前的点j,如果在圆外,就让i、j为直径做圆;然后找j之前的点k,如果在圆外就让i、j、k的三角形的外接圆为ans。这个复杂度的分析,据说期望o(n)。

    求三角形外接圆:设三个点为a(x1,y1)b(x2,y2)c(x3,y3),圆心o(x,y),向量ao=(x-x1,y-y1)、bo=(x-x2,y-y2),这两个向量长度相等,就有(x-x1)^2+(y-y1)^2=(x-x2)^2+(y-y2)^2;同理由(x-x1)^2+(y-y1)^2=(x-x3)^2+(y-y3)^2。

    化简后就是解一个二元一次方程组,如果设bx=x2-x1,by=y2-y1,cx=x3-x1,cy=y3-y1,d=2*(bx*cy-by*cx),那么x=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d,y=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define eps 1e-8
    #define maxm 500005
    using namespace std;
    struct point{
        double xi,yi;
    }ai[maxm]={0};
    struct circle{
        point c;double r;
    };
    int cmp(double x,double y){
        if (x-y>eps) return 1;
        if (x-y<-eps) return -1;
        return 0;
    }
    double sqr(double x){return x*x;}
    double dis(point x,point y){return sqrt(sqr(x.xi-y.xi)+sqr(x.yi-y.yi));}
    point center(point a,point b,point c){
        double bx=b.xi-a.xi,by=b.yi-a.yi;
        double cx=c.xi-a.xi,cy=c.yi-a.yi;
        double d=2*(bx*cy-by*cx);
        double xx=(cy*(sqr(bx)+sqr(by))-by*(sqr(cx)+sqr(cy)))/d+a.xi;
        double yy=(bx*(sqr(cx)+sqr(cy))-cx*(sqr(bx)+sqr(by)))/d+a.yi;
        return (point){xx,yy};
    }
    int main(){
        int n,i,j,k;circle ans;
        scanf("%d",&n);
        for (i=1;i<=n;++i) scanf("%lf%lf",&ai[i].xi,&ai[i].yi);
        ans=(circle){ai[1],0.0};
        for (i=1;i<=n;++i)
            if (cmp(dis(ai[i],ans.c),ans.r)>0){
                ans.c=ai[i];ans.r=0;
                for (j=1;j<i;++j)
                    if (cmp(dis(ai[j],ans.c),ans.r)>0){
                        ans.c=(point){(ai[i].xi+ai[j].xi)*0.5,(ai[i].yi+ai[j].yi)*0.5};
                        ans.r=dis(ai[i],ai[j])*0.5;
                        for (k=1;k<j;++k)
                            if (cmp(dis(ai[k],ans.c),ans.r)>0){
                                ans.c=center(ai[i],ai[j],ai[k]);
                                ans.r=dis(ai[i],ans.c);
                            }
                    }
            }printf("%.2f %.2f %.2f
    ",ans.c.xi,ans.c.yi,ans.r);
    }
    View Code

    pollard's pho

    bzoj4522 密钥破解

    题目大意:数论集合。

    思路:先用pollard's pho分解N,用p和q算出r,求出e在r下逆元d,求c^d(mod N)。

    注意:pollard‘s pho的时候可能返回0,这个时候要在用pollard’s pho做一遍(不能在返回的时候判断,那样可能死循环)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #define LL long long
    using namespace std;
    LL ab(LL x){return (x<0LL ? -x : x);}
    void gcd(LL a,LL b,LL &d,LL &x,LL &y){
        if (!b){d=a;x=1LL;y=0LL;return;}
        gcd(b,a%b,d,y,x);y-=a/b*x;}
    LL mul(LL a,LL b,LL p){
        LL c=0LL;
        for (;b;b>>=1LL){
            if (b&1LL) c=(c+a)%p;
            a=(a+a)%p;
        }return c;}
    LL mi(LL a,LL b,LL p){
        LL c=1LL;
        for (;b;b>>=1LL){
            if (b&1LL) c=mul(c,a,p);
            a=mul(a,a,p);
        }return c;}
    LL pho(LL x,LL c){
        LL i,k,y,x0,d,a,b;
        i=1LL;k=2LL;
        y=x0=(LL)rand()%x;
        while(true){
            ++i;x0=(mul(x0,x0,x)+c)%x;
            gcd(ab(y-x0),x,d,a,b);
            if (d!=1LL&&d!=x) return d;
            if (i==k){y=x0;k+=k;}
        }
    }
    int main(){
        LL e,nn,c,d,n,p=0LL,q,r;
        scanf("%I64d%I64d%I64d",&e,&nn,&c);
        while(!p) p=pho(nn,rand()%(nn-1LL)+1LL);
        q=nn/p;r=(p-1LL)*(q-1LL);
        gcd(e,r,p,d,q);d=(d%r+r)%r;
        n=mi(c,d,nn);
        printf("%I64d %I64d
    ",d,n);
    }
    View Code
  • 相关阅读:
    python基础学习笔记(五)
    python进阶学习笔记(一)
    python基础学习笔记(七)
    LoadRunner 技巧之 脚本设计
    python基础学习笔记(八)
    python基础学习笔记(三)
    python基础学习笔记(十一)
    性能测试知多少性能分析与调优的原理
    python基础学习笔记(十)
    python基础学习笔记(六)
  • 原文地址:https://www.cnblogs.com/Rivendell/p/4780434.html
Copyright © 2011-2022 走看看