zoukankan      html  css  js  c++  java
  • 2017-2-17第一周周赛题解

     A题很水的几何题

    套一下向量的旋转公式即可

     1 #include<stdio.h>
     2 #include<queue>
     3 #include<math.h>
     4 using namespace std;
     5 const double PI=acos(-1);
     6 struct Node
     7 {
     8     double x,y;
     9     int angel;
    10     void rotate()
    11     {
    12         double t=angel*PI/180,a;
    13         a=cos(t)*x-sin(t)*y;
    14         y=sin(t)*x+cos(t)*y;
    15         x=a;
    16     }
    17 }vec;
    18 int main()
    19 {
    20     int t,x,n;
    21     char op[10];
    22     while(scanf("%lf%lf%d",&vec.x,&vec.y,&vec.angel)!=EOF)
    23     {
    24         vec.rotate();
    25         printf("%f %f
    ",vec.x,vec.y);
    26     }
    27     return 0;
    28 }
    A题代码

    B题

    也是大水题,虽然题目说了那么长,但其实置换乘法,仅仅只是映射的复合而已,若p1代表的映射是f1,p2代表的映射是f2,

    那么两个置换做乘法的结果所代表的映射就是f1(f2(i))。

    这题求一下逆映射就行了。

     1 #include<stdio.h>
     2 #include<queue>
     3 #include<math.h>
     4 using namespace std;
     5 int inv[50];
     6 int main()
     7 {
     8     int t,x,n,i;
     9     char op[10];
    10     while(scanf("%d",&n)!=EOF)
    11     {
    12         for(i=1;i<=n;i++)
    13         {
    14             scanf("%d",&x);
    15             inv[x]=i;
    16         }
    17         for(i=1;i<=n;i++)
    18         {
    19             if(i>1)
    20                 printf(" ");
    21             printf("%d",inv[i]);
    22         }
    23         puts("");
    24     }
    25     return 0;
    26 }
    B题代码

    C题

    C题也比较水,在理解清楚置换的概念之后,可以发现置换乘法仅仅是映射的复合而已,每次乘法都可以在O(n)时间内搞定

    ,然后写个快速幂就行了。

     1 #include<stdio.h>
     2 #include<queue>
     3 #include<math.h>
     4 using namespace std;
     5 struct ZhiHuan
     6 {
     7     int arr[30],size;
     8     void mul(ZhiHuan b)
     9     {
    10         int i;
    11         for(i=1; i<=size; i++)
    12             arr[i]=b.arr[arr[i]];
    13     }
    14     void put()
    15     {
    16         int i;
    17         for(i=1; i<=size; i++)
    18         {
    19             if(i>1)
    20                 printf(" ");
    21              printf("%d",arr[i]);
    22         }
    23         puts("");
    24     }
    25 } e,a,b;
    26 ZhiHuan pow(ZhiHuan a,int n)
    27 {
    28     ZhiHuan ans=e;
    29     while(n)
    30     {
    31         if(n&1)
    32             ans.mul(a);
    33         a.mul(a);
    34         n>>=1;
    35     }
    36     return ans;
    37 }
    38 int main()
    39 {
    40     int t,x,n,i,m;
    41     char op[10];
    42     for(i=1;i<30;i++)
    43         e.arr[i]=i;
    44     while(scanf("%d%d",&n,&m)!=EOF)
    45     {
    46         a.size=n;
    47         e.size=n;
    48         for(i=1;i<=n;i++)
    49         {
    50             scanf("%d",&a.arr[i]);
    51         }
    52         b=pow(a,m);
    53         b.put();
    54     }
    55     return 0;
    56 }
    C题解代码

    D题:

    首先我先构造递推表达式

    其中E是单位阵,O是零矩阵

    我们发现这和线性递推式很像,只是特殊在系数是矩阵而已。

    我把这个递推式的矩阵写出来

    这时我们发现,这个递推式可以用分块阵来表示,在配合快速幂求一下这个分块阵的n次方就能轻松求出Sn

    这里有个小技巧,我们很容发现分块阵的任何次方中,右上永远是零矩阵,右下永远是单位阵。用这个特性能化简一些计算过程

     下面是47ms的代码,复杂度(log(k)*n^3)

      1 #include<stdio.h>
      2 #include<string.h>
      3 #define Nmax 10100
      4 int mod,degree;
      5 struct matrix
      6 {
      7     int  m[40][40];
      8     void put()
      9     {
     10         int i,j;
     11         for(i=0; i<degree; i++)
     12         {
     13             for(j=0; j<degree; j++)
     14             {
     15                 if(j)
     16                     printf(" ");
     17                 printf("%d",m[i][j]);
     18             }
     19             puts("");
     20         }
     21     }
     22     matrix operator *(const matrix &b)const
     23     {
     24         matrix ans;
     25         memset(ans.m,0,sizeof(ans.m));
     26         int i,j,k;
     27         for(i=0; i<degree; i++)
     28         {
     29             for(j=0; j<degree; j++)
     30             {
     31                 for(k=0; k<degree; k++)
     32                 {
     33                     ans.m[i][j]+=m[i][k]*b.m[k][j];
     34                 }
     35                 ans.m[i][j]%=mod;
     36             }
     37         }
     38         return ans;
     39     }
     40     matrix operator +(const matrix &b)const
     41     {
     42         matrix ans;
     43         int i,j;
     44         for(i=0; i<degree; i++)
     45         {
     46             for(j=0; j<degree; j++)
     47                 ans.m[i][j]=(m[i][j]+b.m[i][j])%mod;
     48         }
     49         return ans;
     50     }
     51 } E,O;
     52 struct BigMat
     53 {
     54     matrix A,B,C,D;
     55 };
     56 void matpow(matrix p,int n)
     57 {
     58     BigMat temp,ans;
     59     matrix A,C;
     60     ans.A=E;ans.B=O;
     61     ans.C=O;ans.D=E;;
     62     temp.A=p;temp.B=O;
     63     temp.C=E;temp.D=E;
     64     while(n)
     65     {
     66         if(n&1)
     67         {
     68             A=ans.A*temp.A;
     69             C=ans.C*temp.A+temp.C;
     70             ans.A=A;
     71             ans.C=C;
     72         }
     73         n>>=1;
     74         A=temp.A*temp.A;
     75         C=temp.C*temp.A+temp.C;
     76         temp.A=A;
     77         temp.C=C;
     78     }
     79     A=ans.C*p;
     80     A.put();
     81 }
     82 int main()
     83 {
     84 
     85     int i,n,k,j,x,l;
     86     matrix a;
     87     memset(E.m,0,sizeof(E.m));
     88     for(i=0; i<40; i++)
     89         E.m[i][i]=1;/**初始化单位阵*/
     90     memset(O.m,0,sizeof(O.m));/**初始化零矩阵*/
     91     scanf("%d%d%d",&n,&k,&mod);
     92     for(i=0; i<n; i++)
     93     {
     94         for(j=0; j<n; j++)
     95         {
     96             scanf("%d",&x);
     97             a.m[i][j]=x%mod;
     98         }
     99     }
    100     degree=n;
    101     matpow(a,k);
    102     return 0;
    103 }
    D题代码

    E题

    考查线段树,我们在区间[l,r]上存下这一区间x分量,y分量。更新时用角度当成标记是大家首先都能想到的。所以我们要在每个节点存下三个angle,x,y.分别代表这一区间的共同旋转过的角度,和这区间旋转共同角度后的x分量和y分量。

    但这题比较麻烦的地方在于,虽然角度是线性叠加的,但x,y上的分量计算时是非线性的,而题目要求要查询的是x,y的分量、所以为了解决这困难。更新时先把标记下放,然后更新标记,最后再从下往上更新x,y分量就行了。查询时查询顶部节点就可以了。这里有个小技巧,为了提高运算速度可以先将sin,和cos先都预处理好

    我线段树用的是完全二叉树形式的数组实现。

    用时1204ms,复杂度(2n+c*log(n))

    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<queue>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    #define come_first min
    #define INF  2e9
    const double PI=acos(-1.0);
    double SIN[365],COS[365];
    struct Node
    {
        double x,y;
        int angle;
        void rotate()
        {
            angle=angle%360;
            if(angle<0)
                angle+=360;
            double temp;
            temp=COS[angle]*x-SIN[angle]*y;
            y=SIN[angle]*x+COS[angle]*y;
            x=temp;
        }
    };
    int len[10005],a[10005];
    struct Segment_tree
    {
        static const int maxn=2<<15;
        int size,temp;
        Node node[maxn];
        void build(int n)
        {
            n+=2;
            size=1;
            while(size<n)
                size<<=1;
            memset(node,0,sizeof(node));
        }
        void build(int n,int a[])
        {
            int i,h=1,m;
            build(n);
            for(i=1; i<=n; i++)
            {
                node[i+size].y=a[i];
            }
            m=n+size;
            for(i=size-1; i>0; i--)
            {
                if(i<<h<=m)
                {
                    if(i<<h==size)
                        h++;
                    node[i].x=node[i+i].x+node[i+i+1].x;
                    node[i].y=node[i+i].y+node[i+i+1].y;
                }
    
            }
            node[0].angle=0;
        }
        void putdown(int s,int t)///将标记放下
        {
            if(s^1)
            {
                putdown(s>>1,t>>1);
            }
            if(node[s].angle)
            {
                node[s<<1].angle+=node[s].angle;
                node[(s<<1)+1].angle+=node[s].angle;
                node[s].angle=0;
            }
            if(node[t].angle)
            {
                node[t<<1].angle+=node[t].angle;
                node[(t<<1)+1].angle+=node[t].angle;
                node[t].angle=0;
            }
        }
        void update(int pos)
        {
            temp=pos<<1;
            if(pos<size)
            {
                node[pos].x=node[temp].x+node[temp+1].x;
                node[pos].y=node[temp].y+node[temp+1].y;
            }
            else
            {
                node[pos].x=0;
                node[pos].y=len[pos-size];
            }
            if(node[pos].angle)
                node[pos].rotate();
        }
        void add(int l,int n,int angle)///更新
        {
            int s=l+size,t=n+size+1;
            putdown(s>>1,t>>1);
            for(; s^t^1; s>>=1,t>>=1)
            {
                if(~s&1)
                {
                    node[s^1].angle+=angle;
    
                }
                update(s);
                update(s^1);
                if(t&1)
                {
                    node[t^1].angle+=angle;
    
                }
                update(t);
                update(t^1);
    
            }
            update(s);
            update(t);
            while(s>1)
            {
                update(s>>1);
                s>>=1;
            }
        }
    } tree;
    
    int main()
    {
        int i,j,n,m,x,y,d,t=1,cas=0,angle;
        double arc;
        for(i=0; i<360; i++)
        {
            arc=(double)i*PI/180;
            SIN[i]=sin(arc);
            COS[i]=cos(arc);
        }
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(cas)
            {
                puts("");
            }
            cas++;
            memset(len,0,sizeof(len));
            for(i=1; i<=n; i++)
            {
                scanf("%d",&len[i]);
                a[i]=180;
            }
            tree.build(n,len);
            while(m--)
            {
                scanf("%d%d",&x,&angle);
                tree.add(x,n,angle-a[x]);
                a[x]=angle;
                printf("%.2f %.2f
    ",tree.node[1].x,tree.node[1].y);
            }
        }
        return 0;
    }
    E题代码

    再丧心病狂加了一堆优化后,加外输入输出优化

    用时141ms

    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<queue>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    #define come_first min
    #define INF  2e9
    const double PI=acos(-1.0);
    double SIN[365],COS[365];
    struct Node
    {
        double x,y;
        int angle;
        void rotate()
        {
            angle=angle%360;
            if(angle<0)
                angle+=360;
            double temp;
            temp=COS[angle]*x-SIN[angle]*y;
            y=SIN[angle]*x+COS[angle]*y;
            x=temp;
        }
    };
    int len[10005],a[10005];
    const int maxn=2<<15;
    int size,temp;
    Node node[maxn];
    void build(int n)
    {
        n+=2;
        size=1;
        while(size<n)
            size<<=1;
        memset(node,0,sizeof(node));
    }
    void build(int n,int a[])
    {
        int i,h=1,m;
        build(n);
        for(i=1; i<=n; i++)
        {
            node[i+size].y=a[i];
        }
        m=n+size;
        for(i=size-1; i>0; i--)
        {
            if(i<<h<=m)
            {
                if(i<<h==size)
                    h++;
                node[i].x=node[i+i].x+node[i+i+1].x;
                node[i].y=node[i+i].y+node[i+i+1].y;
            }
        }
        node[0].angle=0;
    }
    void putdown(int s,int t)///将标记放下
    {
        if(s^1)
        {
            putdown(s>>1,t>>1);
        }
        if(node[s].angle)
        {
            node[s<<1].angle+=node[s].angle;
            node[s<<1^1].angle+=node[s].angle;
            node[s].angle=0;
        }
        if(node[t].angle)
        {
            node[t<<1].angle+=node[t].angle;
            node[t<<1^1].angle+=node[t].angle;
            node[t].angle=0;
        }
    }
    void inline update(int pos)
    {
        temp=pos<<1;
        if(pos<size)
        {
            node[pos].x=node[temp].x+node[temp^1].x;
            node[pos].y=node[temp].y+node[temp^1].y;
        }
        else
        {
            node[pos].x=0;
            node[pos].y=len[pos-size];
        }
        if(node[pos].angle)
            node[pos].rotate();
    }
    void add(int l,int n,int angle)///更新
    {
        int s=l+size,t=n+size+1;
        putdown(s>>1,t>>1);
        for(; s^t^1; s>>=1,t>>=1)
        {
            if(~s&1)
            {
                node[s^1].angle+=angle;
    
            }
            update(s);
            update(s^1);
            if(t&1)
            {
                node[t^1].angle+=angle;
    
            }
            update(t);
            update(t^1);
    
        }
        update(s);
        update(t);
        while(s>1)
        {
            update(s>>=1);
        }
    }
    inline void Out(int a)    //输出外挂
    {
        if(a>9)
            Out(a/10);
        putchar(a%10+'0');
    
    }
    int tmp;
    void write(double a)
    {
        if(a<0)
        {
            putchar('-');
            a=-a;
        }
        Out((int)a);
        putchar('.');
        tmp=(a-int(a))*100;
        putchar(tmp/10+'0');
        putchar(tmp%10+'0');
    }
    inline void Read(int &x)
    {
        x=0;
        char c=getchar();
        while (c<'0'||c>'9')
            c=getchar();
        while (c>='0'&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
    }
    int main()
    {
        int i,j,n,m,x,y,d,t=1,cas=0,angle;
        double arc;
        for(i=0; i<360; i++)
        {
            arc=(double)i*PI/180;
            SIN[i]=sin(arc);
            COS[i]=cos(arc);
        }
        while(scanf("%d",&n)!=EOF)
        {
            Read(m);
            if(cas)
            {
                puts("");
            }
            cas++;
            memset(len,0,sizeof(len));
            for(i=1; i<=n; i++)
            {
                // scanf("%d",&len[i]);
                Read(len[i]);
                a[i]=180;
            }
            build(n,len);
            while(m--)
            {
                Read(x);
                Read(angle);
                add(x,n,angle-a[x]);
                a[x]=angle;
                write(node[1].x);
                putchar(' ');
                write(node[1].y);
                putchar('
    ');
            }
        }
        return 0;
    }
    优化后的代码



  • 相关阅读:
    python 4 days
    python 3 days
    python 2 days
    Git学习1-- 简介、命令使用、添加远程仓库方法
    Week2-列表、字符串方法示例
    Week2-购物车程序
    Week2-模块初识和数据类型
    Week1-作业:用户登陆程序
    Week1-Python入门教程(后续完善中)
    Intellij IDEA(eclipse设置)常用快捷键
  • 原文地址:https://www.cnblogs.com/qswg/p/6404272.html
Copyright © 2011-2022 走看看