19年牛客多校第十场记录

H

  • 题意: 给出一个图,只可能为他给出五个图的同构,让判断是哪个图
  • 思路: 根据给出图的特点,求2度,3度,4度点的个数即可
#include<bits/stdc++.h>
#define ll long long
#define FOR(i,l,r)  for(int i=l;i<=r;++i)
using namespace std;
typedef  pair<int,int> pii;
const int N =50;
 
int G[10][10];
int d[10];
 
void solve(){
    memset(G,0,sizeof G);
    memset(d,0,sizeof d);
    int u,v;
    for(int i=1;i<=5;++i){
        scanf("%d%d",&u,&v);
        G[u][v] = 1;
        G[v][u] = 1;
        d[u]++; d[v]++;
    }
    int cnt3 = 0,pos3;
    for(int i=1;i<=6;++i){
        if(d[i]==4) {
            printf("2,2-dimethylbutane
");
            return ;
        }
        if(d[i]==3){
            cnt3++;
            if(cnt3>1){
                printf("2,3-dimethylbutane
");
                return;
            }
            pos3 = i;
        }
    }
    if(cnt3==0){
        printf("n-hexane
");
        return ;
    }
    int cnt2= 0;
    for(int i=1;i<=6;++i){
        if(G[pos3][i]==1 && d[i]==2){
            cnt2++;
        }
    }
    if(cnt2==2){
        printf("3-methylpentane
");
    }else{
        printf("2-methylpentane
");
    }
}
 
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        solve();
    }
 
    return 0;
}

E

  • 题意: 分形,又是一道递归,要确定点在分形的相对位置
  • 思路: 想到了归并排序,利用分治.通过观察样例的图形找到了当前层和下一层访问的规律(题干中就有只是没好好读题)

暴力分治合并水过


#include<bits/stdc++.h>
#define ll long long
#define FOR(i,l,r)  for(int i=l;i<=r;++i)
using namespace std;
typedef  pair<int,int> pii;
const int N =50;
struct point{
    int x,y;
    point(){}
    point(int x,int y):x(x),y(y){}
};
int ord[] = {0,0,1,2,3};
void f(int k,int *cor,vector<point>& ve){
    if(ve.size()<=1 || k<1)    return;
    vector<point> xx[4];
    point cp;
    ll bas = 1<<(k-1);
    for(auto p : ve){
        cp = p;
        if(p.x<= bas && p.y<= bas){
            xx[0].push_back(cp);
        }else if(p.x>bas && p.y<= bas){
            cp.x -= bas;
            xx[1].push_back(cp);
        }else if(p.x<=bas && p.y > bas){
            cp.y -= bas;
            xx[3].push_back(cp);
        }else{
            cp.y -= bas;    cp.x -= bas;
            xx[2].push_back(cp);
        }
    }
    ve.clear();
    f(k-1,cor,xx[cor[3]]);
    f(k-1,cor,xx[cor[2]]);
    swap(cor[2],cor[4]);
    f(k-1,cor,xx[cor[1]]);
    swap(cor[2],cor[4]);
    swap(cor[1],cor[3]);
    f(k-1,cor,xx[cor[4]]);
    swap(cor[1],cor[3]);
    for(int i=1;i<=4;++i){
        for(auto p:xx[cor[i]]){
            cp = p;
            if(cor[i]==1){
                cp.x += bas;
            }
            if(cor[i]==2){
                cp.y += bas;
                cp.x += bas;
            }
            if(cor[i]==3){
                cp.y += bas;
            }
            ve.push_back(cp);
        }
    }
}
int n,k;
vector<point> ve;
int main(){
    scanf("%d%d",&n,&k);
    int x,y;
    for(int i=1;i<=n;++i){
        scanf("%d%d",&x,&y);
        ve.push_back(point(x,y));
    }
    f(k,ord,ve);
    for(auto i:ve){
        printf("%d %d
",i.x,i.y);
    }
    return 0;
}

B

  • 题意: s[1] = "COFFEE", s[2] = "CHICKEN" , s[i] = s[i-2] + s[i-1] , 当s长度大于1e12,则只取前1e12. 求s[n],p->p+9的子串
  • 思路: 递归构造(我写了一发段错误还以为会爆栈,结果是函数参数写的int,爆了)
#include<bits/stdc++.h>
#define lson(p) (p<<1)
#define rson(p) (p<<1|1)
#define ll long long
using namespace std;
const int N = 1010;
const ll ML = 1e12+10;
char s1[] = " COFFEE ";
char s2[] = " CHICKEN ";
ll slen[N];
void pre(){
    slen[1] = 6;
    slen[2] = 7;
    for(int i=3;i<=550;++i){
        slen[i] = slen[i-1] + slen[i-2];
        if(slen[i]>ML)  slen[i] = ML;
    }
}
 
void f(int k,ll pos){
    if(k<=2){
        if(k==1){
            if(pos<=6)
                putchar(s1[pos]);
        }else{
            if(pos<=7)
                putchar(s2[pos]);   
        }
        return ;
    }else if(pos > slen[k-2]){
        f(k-1,pos-slen[k-2]);
        return ;
    }else{
        f(k-2,pos);
        return ;
    }   
}
ll n,m;
int main(){
    int t;
    cin >> t;
    pre();
    while(t--){
        cin >> n >> m;
        for(int i=0;i<10;++i)
            f(n,m+i);
        puts("");
    }
 
    return 0;
}

其实可以直接输出10个,但这题数据范围不大,递归10次也能过其实是直接输入10个没调出来.

D

  • 题意: 中国剩余定理,m[i]不保证是质数所以要用exgcd求逆元,且要判断无解情况.
  • 思路: 比赛时写的大数,取模操作没写出来,python也不会写(看来得学一下py写大数了QAQ),没想到用int128再优化一下运算步骤就可以过了int128NB
#include<bits/stdc++.h>
#define ll long long
#define FOR(i,l,r) for(int i = l ; i <= r ;++i )
#define inf 1<<30
#define eps (1e-9)
using namespace std;
typedef  __int128 ULL;
const int N = 110;
int n;
ll m[N],b[N],mx;
void exgcd(ULL a,ULL b,ULL& d,ULL& x,ULL& y){
    if(!b){d = a; x = 1; y = 0;}
    else{exgcd(b,a%b,d,y,x); y-= x*(a/b);}
}
ULL china(){
    ULL M = 1,d,y,x,A=0;
    for(int i=1;i<=n;++i){
        exgcd(M,m[i],d,x,y);
        ULL mm = m[i]/d;
        if((b[i]-A)%d)  return -1;
        x = (x%mm + mm) %mm;
        ULL k = ((b[i]-A)/d*x%mm+mm)%mm;
        A = (A+(k*M)%(M*mm));
        M = mm*M;
    }
    return A;
}
void print(__int128 x){
    static char s[50];
    int cnt = 0;
    while(x>0){
        s[cnt++] = x%10 + '0';
        x/=10;
    }
    for(int i=cnt-1;i>=0;--i)   putchar(s[i]);
    if(cnt==0)  putchar('0');
    puts("");
}
 
int main(){
    cin >> n >> mx;
    for(int i=1;i<=n;++i){
        cin >> m[i] >> b[i];
    }
    ULL res = china();
    if(res == -1) puts("he was definitely lying");
    else if(res > mx || res < 0) puts("he was probably lying");
    else print(res);
    return 0;
}
原文地址:https://www.cnblogs.com/xxrlz/p/11372224.html