2019牛客多校第5场总结

人生第一篇博客

 在教练的教导下开启我人生的第一篇博客!由于懒得从第一场开始 那么就从最近的一场开始吧!
  
 学写博客好麻烦我搞了好久才存在这些东西?

  
 那就进入正题。
  
 一队友在地球的另一面与我们联机打比赛。想想这时差也是个狠人。
  
 比赛开始我们在随便看题反正最后还是看榜做题搞啥战略。遂发现A题过的人巨多。 水题!!!
  
 A 题意大概就是给你一个n,输出一个数x ,使得x每位数上的和为n的倍数,并且x也为n的倍数。看看n<=100,必有蹊跷。。。。一番讨论、改进我们得出结论。  
  
 算出n每位数的和sum输出LCM(sum,n)个n就完事!
  

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,sum=0,x;
        cin>>n;
        x=n;
        while(x)
        {
            sum+=x%10;
            x/=10;
        }
        sum=lcm(n,sum);
        for(int i=0;i<sum;i++)
        {
            cout<<n;
        }
        cout<<endl;
    }
    return 0;
}

  
 签到即巅峰。。。。。于是我们因为太菜后面没有出题。

 B题题意x(i)=ax(i-1)+bx(i-2)让你求x(n) 

 这个n大到可怕啊 1 0 1 0 6 10^{10^6} 10106


 一看到x(i)=ax(i-1)+bx(i-2)这个递推式加上这时间这数据!!!这不就是学长教我们的矩阵快速幂吗!!!然而矩阵快速幂的专题还没有开始练。。。。。。die


 于是开始抄找网上模版模仿之写出一堆bug。。。。我还是太菜了在一波瞎搞以后我终于搞定了n不大的时候算出答案了。。。n这么大怎么办。。。这才是这题的重点吧。此时另一队友因为太饿吃东西去了  

 tcl

 开始在网上找x^n在n很大的情况下的快速幂。。。发现了一堆快速幂都不是我想要的?就在这时我看到了希望的曙光。有一个大佬写了一个博客。
  
大佬的博客

  没想到还有这种操作。
  
 采用十进制式的快速幂 
  
 再看看这个n的范围太棒了这简直就是天意呀。套了一波矩阵过了样历 
  
 于是当然是充满自信的交题呀。。。。
  
 结果T了
  
 T!!!!!
  
 不敢相信 优化到最后半个小时都没发现哪里导致了它的龟速。。。。
  
 最后半小时看队友不太靠谱 没有思绪的亚子,我看了看G字符串题好像思路不对,于是签到结束?。
  
 赛后发现B题是真的可惜了!!!不过也学到了
  
 到底T在哪



 区别就在这!!!mod杀我!!!以后要注意mod的使用方式了它真是个不好对付的家伙。

 B题代码就象征性放一下

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
const int MAXN=2;
using namespace std;
typedef long long ll;
int mod;
ll number[1000005];
class Matrix
{
public:
     
    ll m[MAXN][MAXN];
    //二维数组存放矩阵
    Matrix(){}
    //对数组的初始化
    void init(ll num[MAXN][MAXN])
    {
        for(ll i = 0 ; i < MAXN ; i++)
        {
            for(ll j = 0 ; j < MAXN ; j++)
            {
                m[i][j] = num[i][j];
            }
        }
    }
    //重载矩阵的乘法运算
    friend Matrix operator*(Matrix &m1,Matrix&m2)
{
    ll i, j, k;
    Matrix temp;
    for (i = 0; i < MAXN; i++)
    {
        for (j = 0; j < MAXN; j++)
        {
            temp.m[i][j]=0;
            for(k=0;k<MAXN;k++)
            {
                temp.m[i][j]=(temp.m[i][j]+m1.m[i][k] * m2.m[k][j])%mod;
            }
        }
    }
    return temp;
}
    //矩阵的快速幂
    friend Matrix quick(Matrix M ,ll n)
    {
        Matrix tempans;
        //初始化为单位矩阵
        //初始化
        for(ll i = 0 ; i < MAXN ; i++)
        {
            for(ll j = 0 ; j < MAXN ; j++)
            {
                if(i == j)
                    tempans.m[i][j] = 1;
                else
                    tempans.m[i][j] = 0;
            }
        }
        //快速幂(类似整数)
        while(n)
        {
            if(n&1)
            {
                tempans = tempans * M;
            }
            //已经重载了*
            n>>=1;
            M = M * M;
        }
        return tempans;
    }
    friend Matrix quickpow(Matrix M ,char *n,ll len)
    {
        Matrix tempans;
        //初始化为单位矩阵
        //初始化
        for(ll i = 0 ; i < MAXN ; i++)
        {
            for(ll j = 0 ; j < MAXN ; j++)
            {
                if(i == j)
                    tempans.m[i][j] = 1;
                else
                    tempans.m[i][j] = 0;
            }
        }
        //快速幂(类似整数)
        while(len>0)
        {
            if(n[len-1]!='0')
            {
                ll s=n[len-1]-'0';
                Matrix t;
                t=quick(M,s);
                tempans=tempans*t;
            }
            //已经重载了*
            M=quick(M,10);
            len--;
        }
        return tempans;
    }
};
int main ()
{
    int x0,x1,a,b;
    ll num[MAXN][MAXN];
    char s[1000005];
    memset(num,0,sizeof(num));
    Matrix p,po,ans;
    scanf("%d%d%d%d %s%d",&x0,&x1,&a,&b,s,&mod);
    num[0][0]=a;
    num[0][1]=b;
    num[1][0]=1;
    num[1][1]=0;
    p.init(num);
    num[0][0]=x1;
    num[1][0]=x0;
    num[1][1]=0;
    num[0][1]=0;
    po.init(num);
    int l=strlen(s)-1;
    if(s[l]!='0')
        s[l]--;
    else
    {
        while(s[l]=='0')
        {
            s[l]='9';
            l--;
        }
        s[l]--;
    }
    //puts(s);
    // cout<<mod<<endl;
    ans=quickpow(p,s,strlen(s));
    ans=ans*po;
    printf("%d\n",ans.m[0][0]%mod);
    return 0;
}


 赛后听学长说I题是到几何水题,题意大概就是在一个第一象限的矩形里求三个点,X,Y,Z的坐标,使得X到Y的距离为a,X到Z的距离为b,Y到Z的距离为c。
  
 我的思路是以一个点为原点,对三条边排序,最小的边在x轴上(如果比矩形宽那么向上抬一些)那么另两条边的出两个圆的式子相交一算就算出来了另一个坐标。
  
 主要的问题是。。。这谁是X,Y,Z我傻傻分不清啊先开始没读清楚题意。以为随便输出三个点就好了,没想到还得按顺序来的。

 这使我暴躁了一会,到饭点了就打卡下班了。 后来又去打了会球。。。补题。。。还是先写博客吧!开始写博客之旅。。。。博客怎么这么难写。。。。再次暴躁。。。。

 C题补完再更。可能思路有点麻烦???怪我没好好听学长讲题看来得学学几何知识。




 人生啊!

 我觉得我的代码没毛病啊!!!迷之自信

 还是保存一波代码吧。虽然是错的,果然还是得按题解来吗?

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef long double lb;
const double eps=1e-7;
lb w,h;
lb a[3],ans[2][3],fina[2][3],b[3];
int flag=0;
lb dis(lb x1,lb y1,lb x2,lb y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
void pan(lb xx,lb xy,lb yx,lb yy,lb zx,lb zy)
{
    if(dis(xx,xy,yx,yy)-b[0]<eps&&dis(xx,xy,zx,zy)-b[1]<eps&&dis(yx,yy,zx,zy)-b[2]<eps)
    {
        if(xx<=w&&xy<=h&&yx<=w&&yy<=h&&zx<=w&&zy<=h)
        {
            fina[0][0]=xx;
            fina[1][0]=xy;
            fina[0][1]=yx;
            fina[1][1]=yy;
            fina[0][2]=zx;
            fina[1][2]=zy;
            printf("%.12Lf %.12Lf %.12Lf %.12Lf %.12Lf %.12Lf\n",fina[0][0],fina[1][0],fina[0][1],fina[1][1],fina[0][2],fina[1][2]);
            flag=1;
            return ;
        }
        
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        lb x0,y0,X,Y;
        flag=0;
        scanf("%Lf%Lf%Lf%Lf%Lf",&w,&h,&a[0],&a[1],&a[2]);
        for(int i=0;i<3;i++)
            b[i]=a[i];
        sort(a,a+3);
        ans[0][0]=0.0;
        ans[1][0]=0.0;
        if(w>=a[1])
        {
            x0=a[0];
            ans[1][1]=0.0;
            ans[0][1]=a[0];
            X=(x0*x0+a[2]*a[2]-a[1]*a[1])/(2*x0);
            Y=sqrt(a[2]*a[2]-X*X);
        }
        else
        {
            lb t,A,B,C;
            ans[0][1]=w;
            ans[1][1]=sqrt(a[0]*a[0]-w*w);
            x0=w;
            y0=sqrt(a[0]*a[0]-w*w);
            t=x0*x0+y0*y0+a[2]*a[2]-a[1]*a[1];
            A=(1.0+(x0*x0)/(y0*y0));
            B=(-x0*t)/(y0*y0);
            C=(t*t/(4*y0*y0)-a[2]*a[2]);
            X=(-B+sqrt(B*B-4*A*C))/(2*A);
            Y=sqrt(a[2]*a[2]-X*X);
        }
        ans[0][2]=X;
        ans[1][2]=Y;
        if(!flag) pan(ans[0][0],ans[1][0],ans[0][1],ans[1][1],ans[0][2],ans[1][2]);
        if(!flag) pan(ans[0][0],ans[1][0],ans[0][2],ans[1][2],ans[0][1],ans[1][1]);
        if(!flag) pan(ans[0][1],ans[1][1],ans[0][0],ans[1][0],ans[0][2],ans[1][2]);
        if(!flag) pan(ans[0][1],ans[1][1],ans[0][2],ans[1][2],ans[0][0],ans[1][0]);
        if(!flag) pan(ans[0][2],ans[1][2],ans[0][0],ans[1][0],ans[0][1],ans[1][1]);
        if(!flag) pan(ans[0][2],ans[1][2],ans[0][1],ans[1][1],ans[0][0],ans[1][0]);
        if(!flag) pan(ans[1][0],ans[0][0],ans[1][1],ans[0][1],ans[1][2],ans[0][2]);
        if(!flag) pan(ans[1][0],ans[0][0],ans[1][2],ans[0][2],ans[1][1],ans[0][1]);
        if(!flag) pan(ans[1][1],ans[0][1],ans[1][0],ans[0][0],ans[1][2],ans[0][2]);
        if(!flag) pan(ans[1][1],ans[0][1],ans[1][2],ans[0][2],ans[1][0],ans[0][0]);
        if(!flag) pan(ans[1][2],ans[0][2],ans[1][0],ans[0][0],ans[1][1],ans[0][1]);
        if(!flag) pan(ans[1][2],ans[0][2],ans[1][1],ans[0][1],ans[1][0],ans[0][0]);
    }
    return 0;
}

 不知道错在哪。。。希望有一天能够领悟!

题解思路
 初级题都做不出来的我好菜啊。。。。

 在观摩了一波别人的代码以后,终于ac了。差不多它是每种可能都算过去,碰到合适的就输出,算第三个坐标的时候运用了角度好像的确比我列式子快多了。

 学到了

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
const double eps=1e-12;
double w,h,a,b,c;
struct poi
{
    double x,y;
    poi(){};
    poi(double x,double y):x(x),y(y){}
}pp[3];
bool solve(double aa,double bb,double cc,int xx,int yy,int zz)
{
    pp[xx]=poi(0.0,0.0);
    double ang=acos((aa*aa+bb*bb-cc*cc)/(2.0*aa*bb));
    if(aa<=w) pp[zz]=poi(aa,0.0);
    else
    {
        pp[zz]=poi(w,sqrt(aa*aa-w*w));
        ang+=acos(w/aa);
    }
    pp[yy]=poi(bb*cos(ang),bb*sin(ang));
    if(0.0-eps<=pp[yy].x&&pp[yy].x<=w+eps&&0.0-eps<=pp[yy].y&&pp[yy].y<=h+eps)
    {
        printf("%.12f %.12f %.12f %.12f %.12f %.12f\n",pp[0].x,pp[0].y,pp[1].x,pp[1].y,pp[2].x,pp[2].y);
        return 1;
    }
    return 0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lf%lf%lf%lf%lf",&w,&h,&a,&b,&c);
        if(solve(a,b,c,0,2,1)) continue;
        if(solve(a,c,b,1,2,0)) continue;
        if(solve(b,a,c,0,1,2)) continue;
        if(solve(b,c,a,2,1,0)) continue;
        if(solve(c,a,b,1,0,2)) continue;
        if(solve(c,b,a,2,0,1)) continue;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值