2018年4月19日训练日记

昨晚上日常卡题,发挥失常。

下面说一下卡住的题目以及没做的题目。

E:给你一个矩形木板的长a和宽b,你要把它剪成x:y的长宽比例(都为正整数),求最大面积是多少。若不能剪成x:y,输出-1。

由于刚刚G题卡到爆,这道题没过脑子就写了一个长不变砍宽和宽不变砍长然后比较面积的代码,果断WA。最终也没通过。

赛后仔细一想。。。就是个二分。。。先用GCD把x,y约去最大公约数,如果此时x>a||y>b那就是-1。否则,二分一下然后判断是否满足条件即可。

代码:

#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define lson i*2,l,m
#define rson i*2+1,m+1,r
using namespace std;
const ll mo=2e9;
const int maxn=100010;
ll n,m,l,c[maxn],k,x,y;
ll a,d,f,len[maxn];
int tmp,ans,cnt;
bool b[maxn];
ll gcd(ll x,ll y)
{
    while(x^=y^=x^=y%=x);
    return y;
}
bool jud(ll mid)
{
    if(x*mid<=n&&y*mid<=m) return 1;
    return 0;
}
int main() {
    // ios::sync_with_stdio(false);
    ll cas=1,flag;
    // freopen("input.txt","r",stdin);
    // freopen("output.txt","w",stdout);
     while(cin>>n>>m>>x>>y)
     {
         ll tt=gcd(x,y);
         x/=tt;y/=tt;
         ll a=0,b=0;
         if(x>n||y>m) puts("0 0");
         else {
             ll l=1,r=mo;
             while(l<r)
             {
                 ll mid=(l+r)/2;
                 if(jud(mid)) {
                     a=mid*x;b=mid*y;
                     l=mid+1;}
                 else r=mid;
             }
            cout<<a<<" "<<b<<endl;
         }
     }
    return 0;
}

F:给你三个点的坐标(xi,yi),让你判断是否为直角三角形,或者是否可以把其中一个坐标改变1使其成为直角三角形。

论读题的重要性。没读懂就GG。直接枚举然后判一下即可。注意判重点!!!否则会WA on test 31!!!

代码:

#include <bits/stdc++.h>
#define ll int
#define inf 0x3f3f3f3f
#define lson i*2,l,m
#define rson i*2+1,m+1,r
using namespace std;
const int mo=1e9+7;
const int maxn=100010;
ll n,m,l,c[maxn],k;
ll a,d,f,len[maxn];
int tmp,ans,cnt;
bool b[maxn];
ll cas=1,flag,x,y,z,x12,x13,x23;
ll a1,a2,a3,b1,b2,b3;
ll cal(ll a,ll b,ll c,ll d)
{
    return(c-a)*(c-a)+(b-d)*(b-d);
}
bool jud(ll x,ll y,ll z)
{
    if(x+y==z) return 1;
    if(x+z==y) return 1;
    if(z+y==x) return 1;
    return 0;
}
bool chong()
{
    if(a1==a2&&b1==b2) return 0;
    if(a1==a3&&b1==b3) return 0;
    if(a2==a3&&b3==b2) return 0;
    return 1;
}
bool jud2()
{
    a1++;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    a1-=2;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    a1++;
    b1--;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    b1+=2;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    b1--;


    a2++;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    a2-=2;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    a2++;
    b2--;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    b2+=2;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    b2--;

    a3++;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    a3-=2;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    a3++;
    b3--;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    b3+=2;
    if(chong()){
    x12=cal(a1,b1,a2,b2);
    x23=cal(a2,b2,a3,b3);
    x13=cal(a3,b3,a1,b1);
    if(jud(x12,x23,x13)) return 1;
    }
    b3--;
    return 0;
}
int main() {
    // ios::sync_with_stdio(false);
    // freopen("input.txt","r",stdin);
    // freopen("output.txt","w",stdout);
    cin>>a1>>b1>>a2>>b2>>a3>>b3;
     {
         x12=cal(a1,b1,a2,b2);
         x23=cal(a2,b2,a3,b3);
         x13=cal(a3,b3,a1,b1);
         if(jud(x12,x23,x13)) puts("RIGHT");
         else if(jud2()) puts("ALMOST");
         else puts("NEITHER");
     }
    return 0;
}

G:论!读!题!的!重!要!性!!!

题意,给你n个平台,每个平台的位置分别为i*m到i*m+l(0=<i<n),你初始点在0点,每次只能往前跳距离d,问你在什么坐标会掉下平台。

我读成了你跳n步,求最远跳到哪个坐标会掉下去,然后无脑WA。。。卡题卡到爆

直接一个d一个d的加肯定会TLE的。因此我们只枚举n个d,当跳到能掉下去的位置t%m>l(t=i*d,i<n)时就break,如果跳n步还没掉下去就默认为可以一直跳到最后一个平台,注意位置(n-1)*m+l是不会掉下去的,能整除d的话要加个d,否则就是tmp+(d-(tmp%d)),(tmp=(n-1)*m+l)。读题读到心态爆炸。。。

AC代码:

#include <bits/stdc++.h>
#define ll unsigned long long
#define inf 0x3f3f3f3f
#define lson i*2,l,m
#define rson i*2+1,m+1,r
using namespace std;
const int mo=1e9+7;
const int maxn=100010;
ll n,m,l,c[maxn],k;
ll a,d,f,len[maxn];
int tmp,ans,cnt;
bool b[maxn];
int main() {
    // ios::sync_with_stdio(false);
    ll cas=1,flag,x,y;
    // freopen("input.txt","r",stdin);
    // freopen("output.txt","w",stdout);
     while(cin>>n>>d>>m>>l)
     {
         //memset(c,0,sizeof(c));
         ll x=0,t=0;
         int i=0;
         for(;i<n;i++)
         {
             t+=d;
             if(t%m>l) break;
         }
         if(i<n) cout<<t<<endl;
         else
         {
             ll tmp=(n-1)*m+l;
             if(tmp%d==0) cout<<tmp+d<<endl;
             else cout<<(tmp+(d-(tmp%d)))<<endl;
         }
     }
    return 0;
}

I:求最大子矩形周长。n、m都很小,二维树状数组暴力一下矩形的起点和终点即可。比赛的时候没来得及看这道题。。。

代码:(PS:二维树状数组模板是百度的。。。)

#include<bits/stdc++.h>
#define maxn 31
using namespace std;
int a[maxn][maxn];
int lowbit(int x) {
    return x&-x;
}
void add(int x,int y,int val) {
    int i,j,k;
    for (i=x; i<=25;i+=lowbit(i)) {
        for (j=y;j<=25;j+=lowbit(j)) {
            a[i][j]+=val;
        }
    }
}
int sum(int x,int y) {
    int ans=0,i,j;
    for (i=x;i>0;i-=lowbit(i)) {
        for (j=y;j>0;j-=lowbit(j)) {
            ans+=a[i][j];
        }
    }
    return ans;
}
bool ok(int x1,int y1,int x2,int y2){
    int ans=0;
    ans+=sum(x2,y2)+sum(x1-1,y1-1)-sum(x2,y1-1)-sum(x1-1,y2);
    if (ans)return 0;
    return 1;
}
char s[maxn][maxn];
int main(){
    int i,j,k,l,m,n,d;
    while (scanf("%d%d",&n,&m)!=EOF){
        memset(a,0,sizeof(a));
        for(int i=0;i<n;i++) scanf("%s",s[i]);
        for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        {
            add(i+1,j+1,(int)(s[i][j]&15));
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(!(s[i-1][j-1]&15)){
            for(int k=i;k<=n;k++)
            for(int l=j;l<=m;l++)
            if(ok(i,j,k,l)){
                int tmp=2*(k-i+1)+2*(l-j+1);
                ans=max(ans,tmp);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

J:让你构造一个无向图,使节点V成为割点。输出构造的所有边。如果不能构造,输出-1。注意构造的图必须只有一个联通分量。比赛的时候没来得及看,其实并不难。

暴力构造,挑一个点连接节点V,然后从头开始与除挑出的节点之外的所有节点连边。

注意三点:

1、无向图

2、边数m<n-1时无法构造

3、边数大于(n-2)*(n-1)/2+1时无法构造。(仔细想想是不是)

代码:

#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
int a[maxn];
int main(){
    int i,j,k,l,m,n,d;
    while (scanf("%d%d%d",&n,&m,&k)!=EOF){
       if(m>(((n-2)*(n-1)/2)+1)||m<n-1) puts("-1");
       else if(!m) puts("");
       else {
           if(k<n)
           {
               printf("%d %d\n",k,n);
               m--;
               for(int i=1;i<n;i++)
               {
                   if(!m) break;
                   for(int j=i+1;j<n;j++)
               {
                   if(m) {printf("%d %d\n",i,j);m--;}
                   else break;
               }
               }
           }
           else
           {
               printf("%d %d\n",k,n-1);
               m--;
               for(int i=1;i<=n;i++)
               if(i!=n-1){
                   if(!m) break;
                   for(int j=i+1;j<=n;j++)
               if(j!=n-1){
                   if(m) {printf("%d %d\n",i,j);m--;}
                   else break;
               }
               }
           }
       }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lsd20164388/article/details/80010515