zoukankan      html  css  js  c++  java
  • 某厉害的比赛的题解(待补

    北航第十一届程序设计竞赛网络预赛题解

    比赛链接:

    https://biancheng.love/contest-ng/index.html#/29

    官方题解

    http://sd-invol.github.io/2015/12/15/BCPC2015-Online/

    A.模式

    https://biancheng.love/problem/212/index

    对于窝这个外校成员,这道题好麻烦啊= =

    不过我发现我可以点开别的用户的ID,看到学号。

    然后再猜一猜,就知道了计算机系应该是XX06XXXX,软件学院是XX21XXXX

    代码

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    string s;
    int main()
    {
        while(cin>>s)
        {
            if(s[2]=='0'&&s[3]=='6')
                cout<<"SCSE"<<endl;
            else if(s[2]=='2'&&s[3]=='1')
                cout<<"SOFT"<<endl;
            else cout<<"OTHER"<<endl;
        }
    }
    

    B.并联变阻器

    https://biancheng.love/problem/199/index

    题意即统计满足a,b≤N且aba+b是整数的二元组(a,b)的个数,条件也即a,b≤N且(a+b)|ab。

    令r=gcd(a,b),则有gcd(ar,br)=1,再令a=rx,b=ry,那么(a+b)|ab 可以表示为r(x+y)|r2xy,也就是(x+y)|rxy。

    由于x与y互质,所以gcd(x+y,x)=gcd(x+y,y)=gcd(x,y)=1,(x+y)与x,y也是互质的,则必然有(x+y)|r。

    令r=k(x+y),则a=kx(x+y),b=ky(x+y),可以发现a,b≤N对应着x,y≤N−−√,只需要枚举不超过N−−√的互质数对(x,y),即可计算出对应的每一组解,这样做的时间复杂度是O(N−−√2)=O(N)的,其中求最大公约数的部分可以通过预处理达到O(1)。

    注意到本题的数据组数较大,单组数据使用O(N)算法也会超时,但是枚举所有解的时候也确定了这组解是属于N≥max(a,b)的所有N,所以将这组(a,b)统计到对应的max(a,b),再求一遍前缀和即可得到所有答案,预处理复杂度O(N),单点查询O(1)。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6;
    
    int vis[maxn + 50] ,p[maxn + 50],sum[maxn + 50];
    
    int quick_pow(int x , int y){
        int res=1;
    	while(y){
    		if(y&1) res*=x;
    		x*=x;
    		y>>=1;
    	}
    	return res;
    }
    
    int main()
    {
    	for(int i = 1 ; i <= maxn ; ++ i)
            p[i] = 1;
    	for(int i = 2 ; i <= maxn ; ++ i)
    		if(!vis[i]){
    			for(int j = i ; j <= maxn ; j += i){
    				vis[j] = 1;
    				int t = 0 , x = j;
    				while(x % i == 0) x/=i , t ++ ;
    				t=t>>1;
    				p[j]*=quick_pow( i , t );
    			}
    		}
    	for(int i = 1 , a , b ; i <= maxn ; ++ i){
    		int y = i / p[i] , z = i / p[i] / p[i];
    		for(int j = 1 ; ((a = i + y * j) <= maxn) && ((b = j*y + j * j * z) <= maxn) ; ++ j) sum[max(a,b)]++;
    	}
        for(int i = 1 ; i <= maxn ; ++ i) sum[i] += sum[i-1];
        int n ;
        while(~scanf("%d",&n)) printf("%d
    ",sum[n]);
    	return 0;
    }
    

    D.最大公约数

    https://biancheng.love/problem/201/index

    贪心。

    首先要意识到,最后答案每一段的GCD,一定和整个的GCD是一样的。

    所以就直接扫一遍就好了。

    代码

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    #define maxn 100005
    int a[maxn];
    int gcd(int A,int B)
    {
        if(B==0)return A;
        return gcd(B,A%B);
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            int Ans = a[1];
            for(int i=1;i<=n;i++)
                Ans = gcd(Ans,a[i]);
            int ans = 0;
            int tmp = 0;
            for(int i=1;i<=n;i++)
            {
                if(tmp == 0)
                    tmp = a[i];
                tmp = gcd(tmp,a[i]);
                if(tmp == Ans)
                {
                    ans++;
                    tmp = 0;
                }
            }
            printf("%d
    ",ans);
        }
    }
    

    E.矩阵

    https://biancheng.love/problem/202/index

    就给你2500个方程,一共有100个未知数,然后每个方程里面只有两个未知数,每个未知数的系数都是1,

    问你这个方程是否存在一组解。

    大概一眼看到的算法大概就是算一下矩阵的秩,判断他和增广矩阵的秩是否相同就好了

    然而窝TLE了= =

    所以还是老老实实写差分约束吧,按照差值建边之后,再跑spfa,判断是否有负环就好了

    我的判断方法比较偷懒,因为spfa有负环的话,会一直跑下去,所以我只要判断他是否会一直跑下去就好了

    代码

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<vector>
    #include<queue>
    using namespace std;
    
    #define maxn 110
    vector<pair<int,int> > E[maxn];
    int vis[maxn];
    int inq[maxn];
    int d[maxn];
    int main()
    {
        int n,m,k;
        while(cin>>n>>m>>k)
        {
            int flag = 0;
            for(int i=0;i<maxn;i++)
                E[i].clear();
            memset(d,0,sizeof(d));
            memset(vis,0,sizeof(vis));
            memset(inq,0,sizeof(inq));
            for(int i=0;i<k;i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                E[x].push_back(make_pair(n+y,z));
                E[n+y].push_back(make_pair(x,-z));
            }
            queue<int> Q;
            for(int i=1;i<=n+m;i++)
            {
                d[i]=999999;
                E[0].push_back(make_pair(i,0));
            }
            Q.push(0);inq[0]=1;
            int step = 0;
            while(!Q.empty())
            {
                step++;
                if(step>1000000){
                    flag = 1;
                    break;
                }
                int now = Q.front();
                vis[now]=1;
                Q.pop();
                inq[now]=0;
                for(int i=0;i<E[now].size();i++)
                {
                    int next = E[now][i].first;
                    if(d[next]>d[now]+E[now][i].second)
                    {
                        d[next]=d[now]+E[now][i].second;
                        if(inq[next])continue;
                        inq[next]=1;
                        Q.push(next);
                    }
                }
            }
            if(flag)printf("No
    ");
            else printf("Yes
    ");
        }
    }
    

    F.序列

    https://biancheng.love/problem/203/index

    打表找规律,很容易发现答案 = (n+1)!/2

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    const int mod = 1e9+7;
    long long ans[maxn];
    int main()
    {
        ans[1]=1;
        for(int i=2;i<maxn;i++)
            ans[i]=(ans[i-1]*(i+1))%mod;
        int n;
        while(cin>>n)
            cout<<ans[n]<<endl;
    }
    

    H.高中数学题

    https://biancheng.love/problem/205/index

    首先手动推公式,很容易发现An = 2n + 1

    然后我们再打表An的前缀异或,然后很容易发现规律

    long long get(long long x)
    {
        if(x%4==0)return 2LL*x;
        if(x%4==1)return 3LL;
        if(x%4==2)return 2LL*x+2LL;
        if(x%4==3)return 1LL;
    } 
    

    所以,我们就直接跑就好了~

    代码

    #include<bits/stdc++.h>
    using namespace std;
    long long get(long long x)
    {
        if(x%4==0)return 2LL*x;
        if(x%4==1)return 3LL;
        if(x%4==2)return 2LL*x+2LL;
        if(x%4==3)return 1LL;
    }
    int main()
    {
        int t;scanf("%d",&t);
        while(t--)
        {
            long long l,r;
            scanf("%lld%lld",&l,&r);
            printf("%lld
    ",get(l-1)^get(r));
        }
    }
    

    I.神奇宝贝大师

    https://biancheng.love/problem/206/index

    费马点,曼哈顿版本。

    所以X轴与Y轴是分开的。

    非常裸的一道题,由于这道题的数据范围只有2000,就更加裸了……

    直接暴力n^2扫就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 2005
    long long numx[maxn];
    long long numy[maxn];
    
    int main()
    {
        int t;scanf("%d",&t);
        while(t--)
        {
            memset(numx,0,sizeof(numx));
            memset(numy,0,sizeof(numy));
            int n,m;
            scanf("%d%d",&n,&m);
            int x,y,q;
            scanf("%d%d%d",&x,&y,&q);
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    numx[i]+=((x^i)+(y^j))%q;
                    numy[j]+=((x^i)+(y^j))%q;
                }
            }
            long long minx=9999999999999LL,miny=9999999999999LL;
            for(int i=1;i<=n;i++)
            {
                long long temp = 0;
                for(int j=1;j<=n;j++)
                    temp += numx[j]*abs(j-i);
                if(temp<minx)
                    minx = temp;
            }
    
            for(int i=1;i<=m;i++)
            {
                long long temp = 0;
                for(int j=1;j<=m;j++)
                    temp += numy[j]*abs(j-i);
                if(temp<miny)
                    miny = temp;
            }
            printf("%lld
    ",minx+miny);
    
        }
    }
    

    L.偶回文串

    https://biancheng.love/problem/198/index

    这道题是水题

    回文即满足所有字母都是偶数即可

    我们利用异或,来统计每一种状态的数量,那么这个状态对答案的贡献就是(num-1)*(num)/2

    所以这道题就结束了。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    
    map<int,long long> H;
    
    string s;
    int main()
    {
        while(cin>>s)
        {
            H.clear();
            int k = 0;
            H[k]++;
            for(int i=0;i<s.size();i++)
            {
                k^=(1<<(s[i]-'a'));
                H[k]++;
            }
            map<int,long long>::iterator it;
            long long ans = 0;
            for(it = H.begin();it!=H.end();it++)
            {
                long long p = it->second;
                ans += (p-1)*p/2;
            }
            printf("%lld
    ",ans);
        }
    }
    

    M.我是鱼

    https://biancheng.love/problem/210/index

    这道题涨姿势了,一开始我只能想到hash。

    一直没想到怎么只用xor来解决……

    官方题解写的比较清楚:

    一个数和自己异或(⊕)结果为0,所以如果只有一个数是奇数全部异或起来就能得到结果,如果有两个数是奇数,假设为a,b,把所有数异或起来的结果等于a⊕b,设c=a⊕b,则c≠0,c的二进制表示中必有某一位为1,假设为第x位,那么将所有第x位为0的异或起来,所有为1的异或起来就能得到a,b。

    代码

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    #define maxn 1000005
    long long a[maxn];
    int main()
    {
        int n;
        while(cin>>n)
        {
            long long x=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%lld",&a[i]);
                x^=a[i];
            }
            int flag = 0;
            for(int i=0;i<60;i++)
            {
                if((x>>i)&1)
                {
                    flag = i;
                    break;
                }
            }
            long long ans1 = 0,ans2 = 0;
            for(int i=1;i<=n;i++)
            {
                if((a[i]>>flag)&1)ans1^=a[i];
                else ans2^=a[i];
            }
            if(ans1>ans2)swap(ans1,ans2);
            printf("%lld %lld
    ",ans1,ans2);
        }
    }
  • 相关阅读:
    【SCP-GO-100】梦 中 染
    【scp系列】SCP-4711 不便利便利店
    【scp系列】SCP-2298 塑料盒里的生活
    【scp系列】SCP-CN-1219 关云长大战外星人
    【scp系列】SCP-4444 以米斯达之名
    使用Ubuntu搭建Owncloud私有云
    python中函数的使用初步
    IOS自动化环境搭建踩坑指南
    接口测试工具apifox
    windowns上搭建vscode+node.js开发环境
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5046958.html
Copyright © 2011-2022 走看看