Good Bye 2020

补题ing

A. Bovine Dilemma

题目传送门:

A. Bovine Dilemma

思路:

只要暴力找到有多少长度不同的三角形底即可

AC Code

#include<bits/stdc++.h>
using namespace std;
int x[100];
int ans[100];
int main()
{
    
    
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&x[i]);
        int num=0;
        memset(ans,0,sizeof(ans));
        for(int i=1;i<n;i++)
        {
    
    
            for(int j=i+1;j<=n;j++)
            {
    
    
                if(ans[x[j]-x[i]]==0)
                {
    
    
                    ans[x[j]-x[i]]=1;
                    num++;
                }
            }
        }
        printf("%d\n",num);
    }
    //system("pause");
    return 0;
}

B. Last minute enhancements

题目传送门:

B. Last minute enhancements

思路:

简单模拟即可,如果当前数已经出现过,那就加一,记录每个出现过的数。

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
    
    
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        int n;
        scanf("%d",&n);
        int num=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
    
    
            if(a[i]>ans)
            {
    
    
                ans=a[i];
                num++;
            }
            else if(a[i]==ans)
            {
    
    
                ans++;
                num++;
            }
        }
        printf("%d\n",num);
    }
    //system("pause");
    return 0;
}

C. Canine poetry

题目传送门:

C. Canine poetry

思路:

题目不想任何回文子串的存在。那么我们想到一个大的回文串必然存在小的回文串构成。那么我们就可以处理形如每个aa的第二个字符,aba的第三个字符,aaa的第二、三个字符即可。

AC Code

#include<iostream>
#include<string>
using namespace std;
int main()
{
    
    
	int t;
    cin >> t;
	while (t--)
	{
    
    
		string str;
        cin >> str;
		int n = str.size();
		int ans = 0;
		for (int i = 0;i < n;i++)
		{
    
    
			if (str[i] == '#')continue;
			if ( i + 2 <= n - 1&&str[i] == str[i + 2] )
			{
    
    
				ans++;
				str[i+2] = '#';
			}
			if ( i + 1 <= n - 1&&str[i] == str[i + 1])
			{
    
    
				ans++;
				str[i + 1] = '#';
			}
		}
		cout << ans << endl;
	}
}

D. 13th Labour of Heracles

题目传送门:

D. 13th Labour of Heracles

思路:

贪心的想如果一个点的度为n(大于1),那么代表这个点可以多涂(n-1)次颜色,那么每次颜色数量+1的时候,我们就找权值最大的且能涂的点即可。

AC Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int ans[N],f[N];
int num;
LL w[N];
bool cmp(int a,int b)
{
    
    
    return a>b;
}
int main()
{
    
    
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        int n;
        scanf("%d",&n);
        LL sum=0;
        for(int i=1;i<=n;i++)
        {
    
    
            scanf("%lld",&w[i]);
            sum=sum+w[i];
        }
        num=0;
        memset(ans,0,sizeof(ans));
        for(int i=1;i<n;i++)
        {
    
    
            int u,v;
            scanf("%d%d",&u,&v);
            ans[u]++;
            ans[v]++;
            if(ans[u]>=2) f[++num]=w[u];
            if(ans[v]>=2) f[++num]=w[v];
        }
        sort(f+1,f+1+num,cmp);
        for(int i=1;i<n;i++)
        {
    
    
            if(i==1) printf("%lld ",sum);
            else
            {
    
    
                sum=sum+f[i-1];
                printf("%lld ",sum);
            }
        }
        printf("\n");
    }
    //system("pause");
    return 0;
}

E. Apollo versus Pan(好题)

(数学,思维,按位运算)

题目传送门:

E. Apollo versus Pan

思路:

最直接的想法当然是暴力,那么n3的复杂度显然是会炸的,别说是n3了,就算是n2也是灰会炸的。那么我们就想到大概率应该对每个数的每一位有一个预处理的操作。我们先将公式变化一下:
在这里插入图片描述

在这里插入图片描述
那么显然问题就转化成了两个中括号中的数该怎么求。我们必然需要枚举每一个j,那么对于第j个数的第i位来说如果当前位是1,那么在与的操作中只有第i位同样是1的数才能贡献2i,在或的操作中只有第i为是0的数,我才能多贡献出2i,我们只要预处理出每一位的1有多少个数即可,那么答案就呼之欲出了。

扫描二维码关注公众号,回复: 12163459 查看本文章

AC Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e5+10;
const LL mod=1e9+7;
LL num[75];
LL a[N],cnt[75];
LL quick_pow(LL a,LL b)
{
    
    
    LL res=1;
    while(b)
    {
    
    
        if(b%2) res=res*a%mod;
        a=a*a%mod;
        b=b/2;
    }
    return res%mod;
}
int main()
{
    
    
    int t;
    scanf("%d",&t);
    for(int i=0;i<=63;i++)
        cnt[i]=quick_pow(2,i);
    while(t--)
    {
    
    
        memset(num,0,sizeof(num));
        int n;
        scanf("%d",&n);
        LL ans=0;
        for(int i=1;i<=n;i++)
        {
    
    
            LL x;
            scanf("%lld",&x);
            ans=(ans+x)%mod;
            a[i]=x;
            int k=0;
            while(x)
            {
    
    
                if(x%2) num[k]++;
                k++;
                x=x/2;
            }
        }
        LL sum=0;
        for(int i=1;i<=n;i++)
        {
    
    
            LL f1=0,f2=ans;
            LL x=a[i];
            int k=0;
            while(x)
            {
    
    
                if(x%2==1)
                {
    
    
                    f1=(f1+cnt[k]*num[k]%mod)%mod;
                    f2=(f2+cnt[k]*(n-num[k])%mod)%mod;
                }
                k++;
                x=x/2;
            }
            sum=(sum+f1*f2%mod)%mod;
        }
        printf("%lld\n",sum);
    }
    //system("pause");
    return 0;
}

F. Euclid’s nightmare(好题)

(思维,并查集)

题意:

这道题的题目比较难读,我也是看了别人的题解才知道这题是什么意思(本人老菜b了)。Z2的定义是一个模2加法。给你一些向量,要你求出最少需要哪些向量,能组合出最多的不同向量。

思路:

一个向量最多两维是1,我们可以考虑并查集。对于一个向量,如果这个向量中为1的两维没有在一个连通分量里面,表示这个向量是最小覆盖中的向量,并把这个向量中的1的两维连在一起。同时,如果这个向量中的两维已经在一个连通分量里面了,表示这个向量可以由之前的不同向量相加而成。有的向量只有1维为1,我们对这个向量增加一维,进行增广,让这个向量的m+1维为1,就可以用并查集了。本人觉得这个模型还特别像线性代数中的向量的极大无关组,也许学过线代的朋友会有同样的感觉。

AC Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e5+10;
const LL mod=1e9+7;
int fa[N];
int find(int x)
{
    
    
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
queue<int>que;
bool Union(int x,int y)
{
    
    
    int dx=find(x);
    int dy=find(y);
    if(dx==dy) return false;
    else
    {
    
    
        fa[dx]=dy;
        return true;
    }
}
LL quick_pow(LL x,LL y)
{
    
    
    LL res=1;
    while(y)
    {
    
    
        if(y%2) res=res*x%mod;
        x=x*x%mod;
        y=y/2;
    }
    return res;
}
int num=0;
int main()
{
    
    
    int n,m;    //向量的个数和向量的维数
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m+1;i++)
        fa[i]=i;
    for(int i=1;i<=n;i++)
    {
    
    
        int k;
        scanf("%d",&k);
        int a,b;
        if(k==1)
        {
    
    
            scanf("%d",&a);
            if(Union(a,m+1))
            {
    
    
                que.push(i);
                num++;
            }
        }
        else
        {
    
    
            scanf("%d%d",&a,&b);   
            if(Union(a,b))
            {
    
    
                que.push(i);
                num++;
            }
        }
    }
    printf("%lld %d\n",quick_pow(2,num),num);
    while(!que.empty())
    {
    
    
        printf("%d ",que.front());
        que.pop();
    }
    printf("\n");
    //system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Stevenwuxu/article/details/112758499