sdcf day1 qwq比赛题解

写在前面

来到夏令营的第一场比赛,全是水题(第一题除外,不过是原题还是之前做过的,而且是并查集的果题,咕咕咕)

A

链接

点这里

思路

我就不写了,去看luogu题解吧,传送门

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=4e5;
struct data
{
    int nxt,to;
}e[maxn<<1];
int head[maxn],tot;
void add(int u,int v)
{
    e[++tot]=(data){head[u],v};
    head[u]=tot;
}
int f[maxn],n,m,v[maxn],k,a[maxn],cnt,ans[maxn];
int find(int x)
{
    return x==f[x]?x:f[x]=find(f[x]);
}
void dfs(int x)
{
    v[x]=1;
    for (int i=head[x];i;i=e[i].nxt)
    {
        if (!v[e[i].to])
        {
            int f1=find(x),f2=find(e[i].to);
            if (f1!=f2) f[f1]=f2;
            dfs(e[i].to);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=0;i<n;++i) f[i]=i;
    for (int i=0;i<m;++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    scanf("%d",&k);
    for (int i=0;i<k;++i) scanf("%d",&a[i]),v[a[i]]=1;
    for (int i=0;i<n;++i)
    {
        if (!v[i])
        {
            cnt++;
            dfs(i);
        }
    }
    ans[k]=cnt;
    memset(v,0,sizeof(v));
    for (int i=0;i<k;++i) v[a[i]]=1;
    for (int i=k-1;i>=0;--i)
    {
        v[a[i]]=0; 
        cnt++;
        for (int j=head[a[i]];j;j=e[j].nxt)
        {
            if (!v[e[j].to])
            {
                int f1=find(a[i]),f2=find(e[j].to);
                if (f1!=f2)
                {
                    f[f2]=f1;
                    cnt--;
                }
            }
        }
        ans[i]=cnt;
    }
    for (int i=0;i<=k;++i) printf("%d\n",ans[i]);
    return 0;
}

B

链接

点这里

翻译

我们有一串字母\('a'\)\('b'\)。 我们想对它进行一些操作。 在每一步中,我们在字符串中选择一个子串\(“ab”\),并将其替换为字符串\(“bba”\)
如果我们没有\(“ab”\)作为子串,我们的工作就完成了。 打印我们应该执行的最小步骤数,以便以\(10 ^ 9 + 7\)模式完成工作。
如果字符串中某个字母'a'后面有一个字母'b',则字符串“ab”显示为子字符串。

思路

我们可以看出来每次把\(ab\)换成\(bba\)相当于把b全部提前把\(a\)放后面,所以只要统计\(b\)的数量在进行累加就行了,注意的是每次累计后b的计数器要乘\(2\)

代码


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
#define int long long int
inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
const int mod=1e9+7;
string p;
int ans=0;
int js;
signed main()
{
	cin>>p;
	int len=p.length() ;
	for(int i=len-1;i>=0;--i)
	{
		if(p[i]=='b') {js++;js%=mod;}
		else {ans+=js%mod;ans%=mod;js=(js*2)%mod;}
	}
	cout<<ans;
	return 0;
}

C

链接

点这里

翻译

思路

首先明确一点

想要\(gcd(省略.....)=1\)就一定要让a数组内全是偶数,所以我们可以从这里下手

下面列举一下可能的情况
操作前---------操作后
奇数,奇数---------偶数,偶数
奇数,偶数---------奇数,奇数
偶数,奇数---------奇数,奇数
偶数,偶数---------偶数,偶数

如果原来两个数都是偶数的话,那么操作数为0.
如果原来两个数都是奇数的话,那么操作数为1.
如果原来两个数是一奇一偶的话,那么操作数为2.

所以就\(ok\)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<cstring>
using namespace std;
#define int long long int
inline int read() {
	char c = getchar();
	int x = 0, f = 1;
	while(c < '0' || c > '9') {
		if(c == '-') f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
const int N=300011;
int py_gcd(int x,int y) {
	if(y==0) return x;
	else return py_gcd(y,x%y);
}
int n;
int a[N];
int p;
int ans;
signed main() {
	cin>>n;
	for(int i=1; i<=n; ++i)	a[i]=read();
	int gcds=a[1];
	for(int i=2; i<=n; ++i)	gcds=py_gcd(gcds,a[i]);
	if(gcds>1) {
		cout<<"YES"<<'\n'<<0;
		return 0;
	}
	//处理2个奇数的情况 
	for(int i=1; i<=n; ++i) {
		if((a[i]&1) && (a[i+1]&1)) {
			ans++;
			int tmp;
			tmp=a[i];
			a[i]=-2*a[i+1];
			a[i+1]=2*tmp;
		}
	}
	//一个奇数的一个偶数的情况 
	for(int i=1; i<=n; ++i) {
		if(a[i]&1) ans+=2;
	}
	cout<<"YES"<<'\n'<<ans;
	return 0;
}
//   n个数,n<=1e5,操作:把ai,ai+1 替换成 a[i]-a[i+1],a[i]+a[i+1],问gcd(a1,a2..an)>1的最少操作次数.
posted @ 2019-07-23 10:23  pyyyyyy  阅读(217)  评论(1编辑  收藏  举报