zoukankan      html  css  js  c++  java
  • AtCoder Regular Contest 094

    AtCoder Regular Contest 094


    C - Same Integers

    题意:

    给定(a,b,c)三个数,可以进行两个操作:1.把一个数+2;2.把任意两个数+1。求最少需要几次操作将三个数变为相同的数。

    分析:

    可以发现如果三个数的奇偶性相同直接加就可以了,对于奇偶性不同的,先把奇偶性相同的两个数都+1,然后按照相同的处理就可以了。可以证明没有更好的方案。

    #include <bits/stdc++.h>
    using namespace std;
    int a,b,c,flag,ans,maxx;
    int main()
    {
    	cin>>a>>b>>c;
    	if(a%2==b%2&&b%2==c%2){
    		maxx=max(a,max(b,c));
    		ans+=(maxx*3-a-b-c)/2;
    	} else {
    		maxx=max(a,max(b,c));
    		flag=(a%2+b%2+c%2);
    		maxx+=(maxx%2==(flag==2));
    		ans+=(maxx*3-a-b-c-2)/2;
    		ans+=1;
    	}
    	cout<<ans;
    }
    

    D - Worst Case

    题意:

    给出(Q)组询问,每组询问给出两个数(A_i,B_i),问有多少个二元组((x,y))使(x imes yle A_i imes B_i),其中每个数最多使用两次。
    给出的(A_i,B_i)包含在使用次数中。

    分析:

    可以观察得到小于(sqrt{A_i imes B_i})的数可以随便组合并且一定保证合法。并且无法找出另一种方式使其比这种分配方式更加优秀。

    那么直接计算即可,可以设(A_i imes B_i)(p)(sqrt{A_i imes B_i})(l),那么如果(l imes(l+1)<p)的话,(ans=2 imes(l-1)+1)否则则不(+1)
    考虑(p)正好为完全平方数的情况,如果(A_i,B_i)恰好等于(l)则不用管,否则一定会占用其中一个位置,所以需要相应减去1.

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll q,a,b,cnt,p,l;
    int main()
    {
    	cin>>q;
    	while(q--){
    		cin>>a>>b;
    		p=a*b;
    		l=sqrt(p);
    		if(l*(l+1)<p) cnt=2*(l-1)+1;
    		else cnt=2*(l-1);
    		if(l*l==p&&a!=b) cnt--;
    		if(a*b==4) cnt=1;
    		cout<<cnt<<endl;
    	}
    }
    

    E - Tozan and Gezan

    题意:

    给出(a,b)(sum a=sum b)两个数列,A,B两人分别给数列中的数进行-1操作,当序列中的数都相同时停止,A希望轮数尽量多,B希望轮数尽量少,求至少会进行多少轮。

    分析:

    貌似比上一道题还要简单一些。

    观察得出当所有数都一样是,答案是0,当有任何一组数不一样是,假设(a_i<b_i)那么就可以一直缩减到0,如果(a_i>b_i)那么就可以把另一组数减小到0,因为这一组数肯定是B是无力回天了。

    那么直接找到B中最小的那个就可以了。

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int MAXN=2e6+7;
    ll a[MAXN],b[MAXN],n,sum,minn=1e9+7;
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>a[i]>>b[i];
    		sum+=a[i];
    		if(a[i]>b[i]) if(minn>b[i]) minn=b[i];
    	}
    	if(minn==1e9+7) cout<<0<<endl;
    	else cout<<sum-minn;
    }
    

    F - Normalization

    题意:

    有一个由abc组成的串,可以选择相邻的两个不同的字符替换成第三种字符,问最多能形成多少种不同的串。

    分析:

    思考在那些时候字符串S转换不成T。

    我们可以将a,b,c看成是数字0,1,2。那么发现,每一次更改都不会改变所有数位之和在%3意义下的值。也就是说T所有数位之和如果与S不同,那么是无法转换的。

    如果一开始所有字符都是一样的,那么也就没有什么转换的方法。

    可以发现,如果如果T中字符相邻两两不同,那么他是无法被转换而成的。

    那么是不是剩下的都可以了呢?

    可以通过打表发现,3以内的数据非常奇怪没有规律,但是3以上的符合上述规律。

    DP求解即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=2e6+7;
    #define mo 998244353
    char s[MAXN];
    int f[MAXN][3][3][2],n,ans;
    inline bool check_all()
    {
    	for(int i=1;i<=n-1;i++)
    		if(s[i]!=s[i+1]) return 0;
    	return 1;
    }
    inline bool check_same()
    {
    	for(int i=1;i<=n-1;i++)
    		if(s[i]==s[i+1]) return 0;
    	return 1;
    }
    int main()
    {
    	scanf("%s",s+1);
    	n=strlen(s+1);
    	if(check_all()) {
    		cout<<1;
    		return 0;
    	}
    	if(n<=3){
    		if(n==2) cout<<2;
    		else if(s[1]!=s[2]&&s[2]!=s[3]&&s[1]!=s[3]) cout<<3;
    		else if(s[1]==s[3]) cout<<7;
    		else cout<<6;
    		return 0;
    	}
    	int tot=0;
    	for(int i=1;i<=n;i++)
    		tot+=s[i]-'a';
    	tot%=3;
    	f[1][1][1][0]=f[1][2][2][0]=f[1][0][0][0]=1;
    	for(int i=2;i<=n;i++)
    		for(int j=0;j<=2;j++)
    			for(int k=0;k<=2;k++)
    				for(int p=0;p<=2;p++){
    					int last=(j-k+3)%3;
    					(f[i][j][k][1]+=f[i-1][last][p][1])%=mo;
    					if(k==p) (f[i][j][k][1]+=f[i-1][last][p][0])%=mo;
    					else (f[i][j][k][0]+=f[i-1][last][p][0])%=mo;
    				}
    	for(int i=0;i<=2;i++)
    		(ans+=f[n][tot][i][1])%=mo;
    	cout<<ans+check_same();
    }
    
  • 相关阅读:
    黑客术语1
    leetcode笔记--3 Niim game
    台湾ML笔记--1.2 formalize the learning probelm
    台湾ML笔记--1.1什么时候适合使用ML
    leetcode笔记--2 reverse string
    leetcode笔记--1 two-sum
    数据挖掘导论笔记1
    python基础----ipython快捷键
    记录新的开始
    编译器错误消息: CS1617: 选项“6”对 /langversion 无效
  • 原文地址:https://www.cnblogs.com/victorique/p/9589937.html
Copyright © 2011-2022 走看看