zoukankan      html  css  js  c++  java
  • 2017 Multi-University Training Contest

    讲一下这场多校赛里面比较简单的三个题

    HDU6045  Is Derek lying?

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6045

    题意:有n道题,甲告诉乙,自己做对x道,对方做对了y道,而每道题有ABC三个选项。现在给出他们的卷子两个字符串,表示他们各自每道题的答案,现在请你通过这两个字符串判断甲是否说谎了。

    思路:这道题一开始并没有想出来,过了很久才想出来,其实仔细想一下,如果甲没有撒谎,那么甲和乙对于一道题给出同样答案个数应该在一个区间内才对。上界是n-max(x,y)+min(x,y),下界应该是max(x+y-n,0)。

    下界比较好理解,比如5个问题,x=3,y=3,那么他们肯定得答对至少相同的一道题,才可以满足。

    对于上界可能比较难想,我们假设x<y,如果甲做的题目乙都做对了,但是乙没有做对的题目,加同样也没有作对而且答案还和乙一样,这是不是就是甲和乙相同答案最大的情况,把这段话转换成代码不就是n-max(x,y)+min(x,y)。我们只要确定甲乙两个的相同答案数在这个区间内说明甲没有说谎,否则就是说谎了。

    代码:

    //Author: xiaowuga
    #include <iostream>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <ctime>
    #include <map>
    #include <bitset>
    #include <cctype>
    #define maxx INT_MAX
    #define minn INT_MIN
    #define inf 0x3f3f3f3f
    #define mem(s,ch) memset(s,ch,sizeof(s))
    #define da cout<<da<<endl
    #define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    #define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    const long long N=80000; 
    using namespace std;
    typedef long long LL;
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);
        int T,n,x,y;
        char q1[N],q2[N];
        cin>>T;
        while(T--){
            cin>>n>>x>>y;
            cin>>q1>>q2;
            int ct=0;
            for(int i=0;i<n;i++) if(q1[i]==q2[i]) ct++;
            int l=x+y-n;
            int r=n-max(x,y)+min(x,y);
            if(ct>=l&&ct<=r) cout<<"Not lying"<<endl;
            else cout<<"Lying"<<endl; 
        }
        return 0;
    }
    View Code

    HDU6047  Maximum Sequence

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6047

    题意:现在有两个数组a,b。a是数组里面有一些数,但是需要处理一个c数组c[i]=a[i]-i,b是可供选择的左边界,用过以后就没有了。然后我们生成以后a数组的后n+1到2*n,我们在求第i个的时候可以选一个左边界,选择这个区间在c这个数组里面的最大值。求如果才能让a[n+1]到a[2*n]这n个数的和最大。

    思路:肯定明白先用小的左边界,尽量可以包含最大值,我们我们对左边界排序,然后建立一个优先队列维护这个最大值。在当前边界大小小于堆顶定边界大小的时候,我们可以一直选这个最大值,大于或者等于的时候,把堆顶删除,然后再比较,直到枚举边界值小于堆顶边界值,然后对于新生成的元素我们把他门插入队。看代码吧。

    代码:

     1 //Author: xiaowuga
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <set>
     5 #include <vector>
     6 #include <queue>
     7 #include <cmath>
     8 #include <cstring>
     9 #include <cstdio>
    10 #include <ctime>
    11 #include <map>
    12 #include <bitset>
    13 #include <cctype>
    14 #define maxx INT_MAX
    15 #define minn INT_MIN
    16 #define inf 0x3f3f3f3f
    17 #define mem(s,ch) memset(s,ch,sizeof(s))
    18 #define da cout<<da<<endl
    19 #define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    20 #define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    21 const long long N=250000;
    22 const long long mod=1e9+7;
    23 using namespace std;
    24 typedef long long LL;
    25 struct Node{
    26     LL val,pos;
    27     bool operator <(const Node &m) const{
    28         if(val!=m.val) return val<m.val;
    29         else{
    30             return pos>=m.pos;
    31         }
    32     }
    33 };
    34 LL a[2*N],b[N];
    35 LL n;
    36 priority_queue<Node>q;
    37 int main() {
    38     ios::sync_with_stdio(false);cin.tie(0);
    39     while(cin>>n){
    40         while(!q.empty()) q.pop();
    41         for(int i=1;i<=n;i++){
    42             cin>>a[i];
    43             q.push((Node){a[i]-i,i});
    44         }
    45         for(int i=1;i<=n;i++) cin>>b[i]; sort(b+1,b+n+1);
    46         int cur=1;
    47         for(LL i=n+1;i<=2*n;i++){
    48             Node t=q.top();
    49             while(b[cur]>t.pos){
    50                 q.pop();
    51                 t=q.top();
    52             }
    53             t=q.top();
    54             a[i]=t.val;
    55             q.push((Node){a[i]-i,i});
    56             cur++;
    57         }
    58         LL sum=0;
    59         for(int i=n+1;i<=2*n;i++) sum=(sum+a[i])%mod;
    60         cout<<sum<<endl;
    61          
    62     }
    63     return 0;
    64 }
    View Code

    HDU6055 Regular polygon

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6055

    题意:给出平面上一些整数坐标的点,问可以形成多少个不同的正多边形。

    思路:首先明确一点,官方题解里面也写出来了,整数点形成正多边形只有正方形(比赛的时候就是一直在证明这个搞了好久,早知道应该大胆猜想)。知道这个以后就很简单,枚举两个点直接可以有公式可以算出另外两个点,注意根据这两个点向量方向,计算出的两对不同的点。比如我枚举x,y会算出a,b,但是枚举y,x就会算出c,d两个点,这两对点分布在x,y这个条线的两侧。我们现在只要判断算出来的两个点是否存在,题解用的是map,我用的直接用一个矩阵来记录,但是需要把这个题移到第一象限,这样所有的点才是都是正的,这样对于点查询复杂度就是O(1),速度比较快。

    代码:

     1 //Author:xiaowuga
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <set>
     5 #include <vector>
     6 #include <queue>
     7 #include <cmath>
     8 #include <cstring>
     9 #include <cstdio>
    10 #include <ctime>
    11 #include <map>
    12 #include <bitset>
    13 #define mem(s,ch) memset(s,ch,sizeof(s))
    14 #define da cout<<da<<endl
    15 #define uoutput(a,i,l,r) for(int i=l;i<r;i++) if(i==l) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    16 #define doutput(a,i,l,r) for(int i=r-1;i>=0;i--) if(i==r-1) cout<<a[i];else cout<<" "<<a[i];cout<<endl;
    17 const long long N=500+10;
    18 using namespace std;
    19 int n;
    20 int pic[1000][1000];
    21 pair<int,int>s[N];
    22 int main() {
    23     while(cin>>n){
    24         long long ct=0;
    25         mem(pic,0);
    26         for(int i=0;i<n;i++){
    27             cin>>s[i].first>>s[i].second;
    28             pic[s[i].first+300][s[i].second+300]=1;
    29         }
    30         for(int i=0;i<n;i++)
    31             for(int j=0;j<n;j++){
    32                 if(i==j) continue;
    33                 pair<int,int>t1,t2;
    34                 int f1=1,f2=1;
    35                 t1.first=s[i].second-s[j].second+s[i].first;
    36                 t1.second=s[j].first-s[i].first+s[i].second;
    37                 if(pic[t1.first+300][t1.second+300]==0) f1=0;
    38                 t2.first=s[i].second-s[j].second+s[j].first;
    39                 t2.second=s[j].first-s[i].first+s[j].second;
    40                 if(pic[t2.first+300][t2.second+300]==0) f2=0;
    41                 if(f1&&f2) {
    42                     ct++;
    43                 }
    44             }
    45         cout<<ct/4<<endl;
    46     }
    47     return 0;
    48 }
    View Code
  • 相关阅读:
    大一励志的我,现在已经大三了
    Jenkins+K8s实现持续集成
    Jenkins搭建自动化测试环境
    软件开发式样书 6
    软件开发式样书 5
    软件开发式样书 4
    软件开发式样书 3
    软件开发式样书 2
    软件开发式样书 1
    Git学习笔记
  • 原文地址:https://www.cnblogs.com/xiaowuga/p/7261064.html
Copyright © 2011-2022 走看看