zoukankan      html  css  js  c++  java
  • 喵哈哈村的魔法考试 Round #17 题解

    喵哈哈村的秘境探险系列。

    A.

    实际上就是求乘积%k是否等于0,显然 a * b % k = (a%k)*(b%k)%k,所以边乘边取模就好了。

    #include<bits/stdc++.h>
    using namespace std;
    
    int main(){
        long long n,k;
        while(cin>>n>>k){
        long long now = 1;
        for(int i=0;i<n;i++){
            long long x;
            cin>>x;
            now = now * x % k;
        }
        if(now == 0)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
        }
    }
    

    B.

    异或是可以前缀和的,因为x^x=0,所以 答案就是sum[r]^sum[l-1]

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+7;
    int q,sum[maxn],n,a[maxn];
    
    int main(){
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        while(cin>>n){
            for(int i=1;i<=n;i++)
                cin>>a[i];
            for(int i=1;i<=n;i++)
                sum[i]=a[i]^sum[i-1];
            cin>>q;
            while(q--){
                int x,y;
                cin>>x>>y;
                cout<<(sum[y]^sum[x-1])<<endl;
            }
        }
    }
    

    C

    不修改,是滑雪的经典题,就是一个记忆化搜搜。

    第一个修改操作是O(1),剩下的每次O(n2)修改,然后O(n2)跑DP就好。。

    #include <bits/stdc++.h>
    using namespace std;
    const int dx[]={0,0,1,-1};
    const int dy[]={1,-1,0,0};
    int f[705][705],mark[705][705],m[705][705];
    int n;
    int S(int x,int y){
        if(mark[x][y])return 0;
        if(f[x][y])return f[x][y];
        f[x][y]=1;
        for(int i=0;i<4;++i){
            int _x=x+dx[i],_y=y+dy[i];
            if(_x>n||_y>n||_x<1||_y<1)continue;
            if(m[_x][_y]>=m[x][y])continue;
            f[x][y]=max(f[x][y],S(_x,_y)+1);
        }
        return f[x][y];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j){
            scanf("%d",&m[i][j]);
        }
        char opt[2];
        int m2,q,w,e,r;
        scanf("%d",&m2);
        for(int i=1;i<=m2;++i){
            scanf("%s",opt);
            if(opt[0]=='C'){
                scanf("%d%d%d",&q,&w,&e);
                m[q][w]=e;
            }
            else if(opt[0]=='S'){
                scanf("%d%d%d%d",&q,&w,&e,&r);
                for(int i=q;i<=e;++i)
                for(int j=w;j<=r;++j)
                mark[i][j]=1;
            }
            else if(opt[0]=='B'){
                scanf("%d%d%d%d",&q,&w,&e,&r);
                for(int i=q;i<=e;++i)
                for(int j=w;j<=r;++j)
                mark[i][j]=0;
            }
            else {
                int ans=0;
                memset(f,0,sizeof(f));
                for(int i=1;i<=n;++i)
                for(int j=1;j<=n;++j){
                    ans=max(ans,S(i,j));
                }
                printf("%d
    ",ans);
            }
        }
        
        return 0;
    }
    

    D

    算法其实很简单,我们以二进制为10111001这个数为例

    原数为:
    10111001

    如果我们不取第一个1,那么后面7位我们可以随意取:
    0*******
    如果我们取第一个,不取第二个,那么后面5位我们可以随意取:
    100*****

    以此类推……

    这样一来,我们就不受原数n的限定了,对于*部分,我们只需用组合数算出放1个1,放2个1,放3个1……的种数(记得加上前面已经确定的数位)
    这样以来,我们也就知道了每种1的个数对应数的总数,题中是为了求乘积,那么快速幂即可

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int L_N=65;
    const LL MOD=10000007;
    LL f[L_N][L_N][2],NUM;
    int val[L_N],len;
    
    LL pow(int d,LL k){
        if(k==0) return 1;
        LL t=pow(d,k/2);
        t=t*t%MOD;
        if(k%2) t=t*d%MOD;
        return t;
    }
    
    int main(){
        scanf("%lld",&NUM);
        
        while(NUM){
            val[++len]=NUM&1;
            NUM>>=1;
        }
        reverse(val+1,val+1+len);
        
        f[0][0][1]=1;
        for(int i=1;i<=len;i++){
            for(int j=0;j<=i;j++){
                f[i][j][0]+=f[i-1][j][0];
                if(val[i]) f[i][j][0]+=f[i-1][j][1];
                if(!val[i]) f[i][j][1]+=f[i-1][j][1];
    
                if(j){				
                    f[i][j][0]+=f[i-1][j-1][0];
                    if(val[i]) f[i][j][1]+=f[i-1][j-1][1];
                }
            }
        }
    
        LL ans=1;
        for(int i=1;i<L_N;i++){
            LL d=f[len][i][0]+f[len][i][1];
            ans=(ans*pow(i,d))%MOD;
        }
        
        printf("%lld
    ",ans);
        
        return 0;
    }
    

    E

    树状数组/线段树来维护每个数的和,便于快速查询sum

    更新的话,就直接暴力更新即可,因为每个数最多更新log(n)次就会到达1或者0

    然后我们用并查集维护一下,如果更新到了1,就指向下一个需要更新的值就好了,直接跳过该值。

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    LL a[100005],c[100005];
    int f[100005],n,m,op,l,r,t;
    int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    int update(int x,LL num){while(x<=n)c[x]+=num,x+=(x&-x);}
    LL sum(int x){LL s=0;while(x)s+=c[x],x-=(x&-x);return s;}
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)f[i]=i,scanf("%lld",&a[i]),update(i,a[i]);
        scanf("%d",&m); f[n+1]=n+1;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&op,&l,&r);
            if(l>r)swap(l,r);
            if(op==1)printf("%lld
    ",(sum(r)-sum(l-1)));
            else for(int j=l;j<=r;update(j,(t=(int)sqrt(a[j]))-a[j]),a[j]=t,
            f[j]=(a[j]<=1)?j+1:j,j=(find(j)==j?j+1:f[j]));
        }
        return 0;
    }
  • 相关阅读:
    非递归实现斐波拉契函数
    二叉树前序、中序遍历得到后序遍历
    python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)
    2018春招-今日头条笔试题-第四题(python)
    2018春招-今日头条笔试题-第三题(python)
    2018春招-今日头条笔试题-第二题(python)
    Karatsuba乘法--实现大数相乘
    NodeJS写模块和引入模块的例子
    nodeJS的了解
    Node.js的适用场景
  • 原文地址:https://www.cnblogs.com/qscqesze/p/6760700.html
Copyright © 2011-2022 走看看