zoukankan      html  css  js  c++  java
  • Codeforces Round #641 (Div. 2)

    A. Orac and Factors

    题解

    (n) 为偶数时, (n) 每次的最小因子(除 (1)以外)都是 (2)

    (n) 为奇数时,(n) 每次的最小因子(除 (1)以外)是奇数,当奇数加上奇数之后为偶数,则后面的 (k-1) 次都是(2)

    解决的思路:不论是不是奇数,先求解出最小的因子(除 (1)以外),再加上 ((k-1)*2)

    代码

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            ll n,k;
            scanf("%lld%lld",&n,&k);
            ll m=sqrt(n),res=n,ret=n;
            for(ll i=2;i<=m;++i){
                if(n%i==0){
                    ret=i;
                    break;
                }
            }
            res+=ret;
            res+=(k-1)*2;
            printf("%lld
    ",res);
        }
        return 0;
    }
    

    B. Orac and Models

    题解

    感觉代码很像筛法,对于任何一个数 (i) ,枚举它所有的最倍数,再根据条件 (a_i<a_j) 用于求解最大值。

    注:初始化的坑很强大。

    代码

    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int maxn = 1e5+5;
    int a[maxn];
    int b[maxn];
    int max(int x,int y){
        return x>y?x:y;
    }
    int main(){
        int t,n;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(int i=1;i<=n;++i){
                b[i]=1;
                scanf("%d",&a[i]);
            }
            int maxx=1;
            for(int i=1;i<=n;++i){
                for(int j=i*2;j<=n;j+=i){
                    if(a[j]>a[i]){
                        b[j]=max(b[j],b[i]+1);
                        maxx=max(maxx,b[j]);
                    }
                }
            }
            printf("%d
    ",maxx);
        }
        return 0;
    }
    

    C. Orac and LCM

    题解

    求解 (gcd({lcm({ai,aj}) | i<j})) 最暴力的解法是 枚举所有的 (i)(j) 来进行求解

    for(int i=1;i<n;++i){
        for(int j=i+1;j<=n;++j){
     		res=gcd(res,lcm(a[i],a[j]));       
        }
    }
    

    就像这样,但实际上会超时的。

    那么可以采用一些优化措施,

    (gcd({lcm({ai,aj}) | i<j})) 可以这样理解,

    枚举每一个 (i) ,使 (c_i=lcm(a_i,a_j)) 满足 (i) 不变并且 (j>i) ,之后计算 (gcd(c_i))

    那就是这样

    for(int i=1;i<n;++i){
        c[i]=a[i];
        for(int j=i+1;i<=n;++j){
            c[i]=lcm(c[i],a[j]);
        }
    }
    int ret=c[1];
    for(int i=2;i<n;++i){
        ret=gcd(ret,c[i]);
    }
    

    你可能会发现一个规律,(c_i) 表示的是 (a_i) 和所有 (a_j)(lcm)

    (namo) ,提前预处理一下所有的 (lcm) 存储到 (b_i) 中。

    后面的就是计算 (a_i)(b_{i+1})(gcd) 了。

    代码

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e5+5;
    typedef long long ll;
    ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
    ll a[maxn];
    ll b[maxn];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        for(int i=n-1;i>0;--i){
            b[i]=gcd(b[i+1],b[i]);
        }
        ll ret=a[1]*b[2]/gcd(a[1],b[2]);
        for(int i=1;i<n;++i){
            ret=gcd(ret,a[i]*b[i+1]/gcd(a[i],b[i+1]));
        }
        printf("%lld
    ",ret);
        return 0;
    }
    

    D. Orac and Medians

    题解

    输出 (yes) 的一个必要条件是数组中存在 (k) ,其次是如果有两个连续的数大于等于 (k) 的话,(namo) 再加上任何一个小于 (k) 的话,这连续的三个数的值 都会大于等于 (k) ,此后依次吞噬小的数,当遇到k时,两个大于等于 (k) 的数放在一起会变成两个 (k) 的。经过这样之后剩下的都是数组可以想象出来都是什么样子的。

    最后筛一个 (a_{i+1},a_{i-1}≥k) 并且(ai<k) 只要满足这种情况就会生成连续三个都大于等于 (k) 的数字。

    总结一下就是满足下列条件之一就输出 (yes)

    • 数组中存在 (k) 并且满足 (a_i,a_{i+1}≥k)
    • 数组中存在 (k) 并且满足 (a_{i+1},a_{i-1}≥k,ai<k)
    • (n=1) 并且存在 (k) (最坑的点)

    代码

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e5+5;
    int a[maxn];
    int b[maxn]={0};
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int n,k;
            int flag=0,f=0;
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;++i){
                scanf("%d",&a[i]);
                if(a[i]>=k&&a[i-1]>=k&&i!=1)flag=1;
                if(a[i]>=k&&a[i-1]<k&&a[i-2]>=k&&i>=2)flag=1;
                if(a[i]==k)f=1;
            }
            if(!f){
                printf("no
    ");
                continue;
            }
            if(flag||n==1){
                printf("yes
    ");
                continue;
            }
            printf("no
    ");
        }
        return 0;
    }
    

    E. Orac and Game of Life

    题解

    根据题意它内部的变化是上下左右有相同的则变,否则不进行改变,其次的话如果图中的某一个位置发生了变化,之后它的变化就会是周期性的变化。

    现在要解决的问题就会是它什么时候发生变化,发生的变化来自于存在至少两个相等的位置扩散来的变化,就像这样

    [0101\1010\0100\---\第一次 \0101\1011\0111\---\第二次\0100\1000\0000\---\第三次\0111\1111\1111\---\第四次\0000\0000\0000\ ]

    一遍 (bfs) 搜索一下,记录一下到达的时间,输出的时候判断一下规律就好了。

    代码

    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e3+5;
    struct node{int x,y;ll val;};
    int step[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    char s[maxn][maxn];
    int vis[maxn][maxn];
    ll dis[maxn][maxn];
    int main(){
        queue<node>Q;
        int n,m,t;
        scanf("%d%d%d",&n,&m,&t);
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                dis[i][j]=1e18+1;
            }
        }
        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){
                for(int k=0;k<4;++k){
                    int x=i+step[k][0];
                    int y=j+step[k][1];
                    if(x>=0&&x<n&&y>=0&&y<m&&s[x][y]==s[i][j]){
                        Q.push({i,j,0});
                        vis[i][j]=1;
                        dis[i][j]=0;
                        break;
                    }
                }
            }
        }
        while(!Q.empty()){
            node p=Q.front();
            Q.pop();
            for(int i=0;i<4;++i){
                int x=step[i][0]+p.x;
                int y=step[i][1]+p.y;
                if(x>=0&&x<n&&y>=0&&y<m&&!vis[x][y]){
                    // cout<<x<<" "<<y<<" "<<p.x<<" "<<p.y<<endl;
                    vis[x][y]=1;
                    dis[x][y]=p.val+1; 
                    Q.push({x,y,dis[x][y]});
                }
            }
        }
        // for(int i=0;i<n;++i){
        //     for(int j=0;j<m;++j)
        //         cout<<dis[i][j]<<" ";
        //     cout<<endl;
        // }
        while(t--){
            int x,y;
            ll q;
            scanf("%d%d%lld",&x,&y,&q);
            x--;y--;
            int val=s[x][y]-'0';
            if(dis[x][y]<=q){
                val=((q-dis[x][y])%2+val)%2;
                printf("%d
    ",val);
            }
            else printf("%d
    ",val);
        }
        return 0;
    }
    
    新赛季的开始
  • 相关阅读:
    Python 数据库骚操作 — MongoDB
    5分钟学会如何玩转云数据库组件(迁移,审计,订阅)
    数据库10大常见安全问题及Top 10 数据库安全工具盘点
    埋在 MYSQL 数据库应用中的17个关键问题!
    MySQL分布式数据库高可用实践:架构、复制机制、多机房
    浅谈如何保障自建数据库的备份恢复机制
    【深度】分布式数据库数据一致性原理说明与实现
    SyncNavigator 破解版 ,做数据同步时所支持的数据库类型
    使用SyncNavigator进行SqlServer或者MYsql数据库的实时、增量同步
    Syncnavigator破解版注册机
  • 原文地址:https://www.cnblogs.com/VagrantAC/p/12884384.html
Copyright © 2011-2022 走看看