zoukankan      html  css  js  c++  java
  • nowcoder(牛客网)OI测试赛3 解题报告

    昨天因为胡搞了一会儿社团的事情,所以错过(逃过)了nowcoder的测试赛。。。。。
    以上,听说还是普及组难度qwq,而且还有很多大佬AK(然而我这么蒻肯定还是觉得有点难度的吧qwq)
    不过我还是日常来补一下题解好了qwq

    T1 数字权重(快速幂)


    这个就是你把式子(sum_{i=2}^n(a_i-a_{i-1})=K)展开就是(a_n-a_1)嘛。。。所以就是水题一个qwq
    但是要注意因为数据范围比较大,所以我们要有快速幂。而且注意不合法情况的特判qwq

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define mod 1000000007
    using namespace std;
    long long n,k,ans=1;
    long long mul(long long x,long long y)
    {
        if(!y) return 1;
        else
        {
            long long ans=mul(x,y>>1);
            if(y&1) return (ans*ans%mod)*(x%mod)%mod;
            else return ans*ans%mod;
        }
    }
    int main()
    {
        scanf("%lld%lld",&n,&k);
        if(k>=10||n==1||k<=-10)
        {
            printf("0
    ");
            return 0;
        }
        if(k<0)
        {
            ans=mul(10,n-2)%mod;
            ans*=10-abs(k);
        }
        else
        {
            ans=mul(10,n-2)%mod;
            ans*=9-k;
        }
        printf("%lld
    ",ans%mod);
        return 0;
    }
    

    T2 毒瘤XOR(异或)(二进制)


    这个我是把原数拆成二进制下的数(30位),然后进行贪心。我们要想输出最小的数,那么就在当前位下如果零的个数小于等于一的个数时让ans该位为0,将这个位置记录下来,然后在最后遍历一遍将其ans+=1<<记录的位数。
    当然暴力地算不太行,所以我们考虑用前缀和qwq......
    然后就60分光荣MLE了。。。我也不知道怎么回事。。。这里附上我的60分代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int n,q;
    int a[MAXN],l[MAXN],r[MAXN],sum[MAXN][32],sum0[MAXN][32],sum1[MAXN][32];
    long long ans;
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            int cur=a[i],cnt=-1;
            while(cur)
            {
                sum[i][++cnt]=cur%2;
                cur>>=1;
            }
            for(int j=0;j<=31;j++)
            {
                if(sum[i][j]==1) sum1[i][j]=sum1[i-1][j]+1,sum0[i][j]=sum0[i-1][j];
                else  sum0[i][j]=sum0[i-1][j]+1,sum1[i][j]=sum1[i-1][j];
                //printf("sum0[%d][%d]=%d sum1[%d][%d]=%d
    ",i,j,sum0[i][j],i,j,sum1[i][j]);
            }
        }
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
            scanf("%d%d",&l[i],&r[i]);
        for(register int i=1;i<=q;i++)
        {
            ans=0;
            for(int j=0;j<=31;j++)
            {
                int cur1=sum0[r[i]][j]-sum0[l[i]-1][j];
                int cur2=sum1[r[i]][j]-sum1[l[i]-1][j];
                if(cur1<cur2||(cur1&&cur2&&cur1==cur2))
                   ans+=1<<j;
            }
            long long ansans=2147483647-ans;
            printf("%lld
    ",ansans);
        }
         
        return 0;
    }
    

    然后发现可以用位运算来优化掉做法,所以。。。。AC代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define MAXN 100010
    using namespace std;
    int n;
    int A[MAXN][31],sum[MAXN][31];
    int main(){
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            ll x;
            scanf("%lld",&x);
            for (int j=0;j<=30;j++) A[i][j]=(x&((ll)1<<(ll)j))!=0;
        }
        for (int i=1;i<=n;i++)
            for (int j=0;j<=30;j++)
                sum[i][j]=sum[i-1][j]+A[i][j];
        int m; scanf("%d",&m);
        while (m--){
            int l,r; scanf("%d %d",&l,&r);
            ll ans=0;
            for (int i=30;i>=0;i--){
                ans<<=1;
                int  num=sum[r][i]-sum[l-1][i];
                if (2*num<(r-l+1)) ans++;
            }
            printf("%lld
    ",ans);
        }
    }
    

    T3 硬币游戏(贪心)


    这个题刚一看时是博弈论???但是再看就发现是简单的贪心。。。。qwq

    题目中有一点描述不清,这里补充一下,该题就是clccle只能取第一列,sarlendy只能取第二列。(刚开始不知道这一点竟然判断起了奇偶性)

    然后我们就贪心地先把都是1的标记到,然后clccle取他那一列是1的,然后sarlendy取他那一列是1的。然后判断大小就行了qwq

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define MAXN 2000010
    using namespace std;
    int n,sum1,score1,score2,done[MAXN];
    char a[MAXN],b[MAXN];
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=2*n;i++)
    		cin>>a[i];
    	for(int i=1;i<=2*n;i++)
    	{
    		cin>>b[i];
    		if(a[i]=='U'&&b[i]=='U') sum1++,done[i]=1;
    	}
    	if(sum1<n)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			if(a[i]=='U'&&done[i]==0) score1++,done[i]=1;
    			if(b[i]=='U'&&done[i]==0) score2++,done[i]=1;
    		}
    		score1+=(sum1+1)/2;
    		score2+=sum1-(sum1+1)/2;
    		if(score1>score2)
    			cout<<"clccle trl!"<<endl;
    		else if(score1==score2||(score1>=n&&score2>=n))
    			cout<<"orz sarlendy!"<<endl;
    		else cout<<"sarlendy tql!"<<endl;
    	}
    	else
    		cout<<"orz sarlendy!"<<endl;
    	return 0;
    }
    

    T4 粉樱花之恋(矩阵快速幂)(斐波那契数列)


    这个一看就是求斐波那契数列前n+1项和的模板题,但是怎么求斐波那契数列的前n项和呢?
    这里我们需要用到一个结论:
    我们用(f_i)来表示斐波那契数列的第(i)项,那么它的前n项和为(sum_{i=1}^nf_i=f_{n+2}-1)

    下面我们来推导~~
    先把左边的展开并+1:

    (sum_{i=1}^nf_i+1)
    (=f_1+f_2+f_3+...+f_n+1)
    (=f_1+f_2+f_3+...+f_n+f_2)
    (=(f_1+f_2)+f_2+f_3+...+f_n)
    (=(f_2+f_3)+f_3+...+f_n)
    (=f_n+f_{n+1})
    (=f_{n+2})

    得证:(sum_{i=1}^nfi=f_{n+2}-1)

    那么其他的就超级简单啦!就是模板嘛。。。。。但是考虑到数据范围过大,所以我们要用(log(n))的矩阵快速幂来做
    如果有矩阵快速幂不会的可以模板(戳我)
    同机房还有dalao用三维矩阵做的,大概就是多开一个来储存和qwq(~~大家可以在我的友链区BLUESKY007 和 dreagonm找到ta们qwq)
    下面放上我的代码qwq

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define mod 998244353
    using namespace std;
    struct Matrix
    {
        long long a[3][3];
    };
    Matrix res,mul;
    long long n,kk[3],ans[3];
    Matrix multi(Matrix x,Matrix y)
    {
        Matrix cur;
        for(int i=1;i<=2;i++)
           for(int j=1;j<=2;j++)
              cur.a[i][j]=0;
        for(int i=1;i<=2;i++)
            for(int j=1;j<=2;j++)
                for(int k=1;k<=2;k++)
                    cur.a[i][j]=(cur.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
        return cur;
    }
    void solve()
    {
        for(int i=1;i<=2;i++)
           for(int j=1;j<=2;j++)
                    ans[i]=(ans[i]+kk[j]*res.a[i][j])%mod;
        printf("%lld
    ",ans[2]-1);
    }
    int main(){
        for(int i=1;i<=2;i++)
           res.a[i][i]=1;
        for(int i=1;i<=2;i++)
           for(int j=1;j<=2;j++)
              mul.a[i][j]=1;
        mul.a[2][2]=0;
        kk[1]=kk[2]=1;
        scanf("%lld",&n);
        if(n==0)
        {
            printf("1
    ");
            return 0;
        }
        if(n==1)
        {
            printf("2
    ");
            return 0;
        }
        n=n+2;
        //n--;
        while(n)
        {
            if(n&1)
               res=multi(res,mul);
            n>>=1;
            mul=multi(mul,mul);
        }
        solve();
        return 0;
    } 
    

    T5 符合条件的整数(高精度)


    这个。。。没写高精度,但是支持__int128啊!所以说。。。我们使用__int128类型就可以轻松水过这个题了。
    注意我们找符合条件的要向上取整qwq
    注意是左闭右开区间qwq,所以记得-1

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #define ll __int128
    inline ll f(int x) {
        ll a=(((ll)1)<<x)-1;
        ll ans=a/7;
        if(a%7!=0) ans++;
        return ans;
    }
    int main(){
        int n, m;
        scanf("%d%d",&n,&m);
        printf("%llu",(unsigned long long)(f(m)-f(n)));
        return 0;
    }`
    

    T6 可爱即正义(字符串)


    这个题这个题。。。。再一次让我认识到了STL大法好!!看到别人手动匹配感觉好心累啊,还是用find()比较happy。
    不过原先一直不知道find()还可以在指定范围内的字符串中查找字符串,今天算是知道了.....
    比如说

        int k=s.find("abc");
        //这个是在字符串s中寻找abc,并且返回第一个位置(即a)
        int k2=s.find("abc",k+1);
        //这个就可以实现在字符串s中寻找abc存在的第二个位置
        //因为我们是从第k+1位开始寻找的
    

    所以说代码就比较短吧qwq。。。。。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    string s;
    int main()
    {
    	cin>>s;
    	int ans=0;
    	int pos=s.find("suqingnianloveskirito");
    	if(pos==-1) {printf("Yes
    %d %d
    ",1,2);return 0;}
    	int pos2=s.find("suqingnianloveskirito",pos+1);
    	if(pos2==-1) {printf("Yes
    %d %d
    ",pos+1,pos+2);return 0;}
    	int pos3=s.find("suqingnianloveskirito",pos2+1);
    	if(pos3==-1) {printf("Yes
    %d %d
    ",pos+1,pos2+2);return 0;}
    	else printf("No
    ");
    	return 0;
    }
    
  • 相关阅读:
    Rsync实现文件同步的算法(转载)
    Python模拟登录cnblogs
    负载均衡中四层和七层的介绍(转帖)
    Lvs+Keepalived实现MySQL高可用
    MySQL配置主主及主从备份
    Vim扩展YouCompleteMe插件
    使用Git
    Django回忆录
    Ansible安装配置及使用
    Hive学习之四 《Hive分区表场景案例应用案例,企业日志加载》 详解
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9638619.html
Copyright © 2011-2022 走看看