牛客周赛 Round 69题解

构造C的歪

 好水的题,先算出来a,b的差,然后让a,b的最大值加上那个差就可以了

#include<bits/stdc++.h>
using namespace std;
#define int long long

int a,b;
signed main()
{
    cin>>a>>b;
    int cha=abs(a-b);
    cout<<max(a,b)+cha;
    return 0;
}

不要三句号的歪

两种方法,第一种是c快速秒 

void solve(){
    i64 a,b,c;
    scanf("%lld,%lld,...,%lld",&a,&b,&c);
    cout<<c-b-1;
}

另一种就是全都看成字符串,然后去求第一个逗号和第二个逗号之间的数和第二个逗号之后的数,然后作差

#include<bits/stdc++.h>
using namespace std;
#define int long long
string s;
signed main()
{
    
    cin>>s;
    int flag1,flag2,flag3;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]==',')
        {
            flag1=i;
            break;
        }
    }
    for(int i=flag1+1;i<s.size();i++)
    {
        if(s[i]==',')
        {
            flag2=i;
            break;
        }
    }
    for(int i=s.size()-1;i>=0;i--)
    {
        if(s[i]==',')
        {
            flag3=i;
            break;
        }
    }
    int ans1=0;
    int ans2=0;
    int flag=1;
    for(int i=flag2-1;i>=flag1+1;i--)
    {
        ans1+=flag*(s[i]-'0');
        flag*=10;
    }
    flag=1;
    for(int i=s.size()-1;i>=flag3+1;i--)
    {
        ans2+=flag*(s[i]-'0');
        flag*=10;
    }
    
    cout<<ans2-ans1-1;
    return 0;
}

仰望水面的歪

思路:纯思维,我们可以将向量转变成矢量的形式,因为经过折射,

所以在z轴的运动距离应当为h+h-z

在x轴运动的距离为x

在y轴运动的距离为y

所以矢量为(x,y,2*h-c)然后将gcd(x,y,2*h-c)消去即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,h;
int x,y,z;
int gcd(int a,int b)
{
    if(b==0)
    {
        return a;
    }
    return gcd(b,a%b);
}
signed main()
{
	cin>>n>>h;
	for(int i=1;i<=n;i++)
	{
		cin>>x>>y>>z;
		int c=h+h-z;
		if(gcd(gcd(x,y),c)==1)
		{
			cout<<x<<" "<<y<<" "<<c<<"\n";
		}
		else
		{
			cout<<x/gcd(gcd(x,y),c)<<" "<<y/gcd(gcd(x,y),c)<<" "<<c/gcd(gcd(x,y),c)<<"\n";
		}
	}
	return 0;
}

 小心火烛的歪

 

思路:这题一看数据范围最大就是7就知道是一个暴力模拟题了,因此我们可以用状压去处理,哪一种燃放计划可用,但是我们要从0为开始存储,所以0位表示当前位,也就是去第一个燃放计划是否要进行,也就是从0,遍历到2^(q)-1即可
ps:要判断有没有一种可能全部都被放了杂物,没有燃放烟花的机会,所以直接输出0种即可

#include <bits/stdc++.h>  
using namespace std;  
#define int long long  

int n, m, q;  
int a[10][10]; // 堆放杂物是1,没有杂物是0  
int b[10][10][10]; // 第k个燃放计划  
int c[10][10];  
string s;  
vector<int> vec;
int minn = LLONG_MAX;  

void solve(int x) {  
    memset(c, 0, sizeof(c));  
    int cnt = 0;  

    for (int k = 0; k < q; k++) { 
        if (x & (1 << k)) { 
            cnt++;  
            for (int i = 1; i <= n; i++) {  
                for (int j = 1; j <= m; j++) {  
                    if (a[i][j] == 0 && b[i][j][k + 1] == 1) {  
                        c[i][j]++;  
                    } else if (a[i][j] == 1 && b[i][j][k + 1] == 1) {  
                        return; 
                    }  
                }  
            }  
        }  
    }  

    
    int flag = 1;  
    for (int i = 1; i <= n; i++) {  
        for (int j = 1; j <= m; j++) {  
            if (a[i][j] == 0 && c[i][j] == 0) {  
                flag = 0; 
                break;  
            }  
        }  
    }  

    if (flag&&minn>cnt) {  
        minn = cnt;
        vec.clear();
		for (int k = 0; k < q; k++) 
		{
			if (x & (1 << k)) 
			vec.push_back(k+1);
		}
        
    }  
}  

signed main() {  
    cin >> n >> m >> q;  
    for (int i = 1; i <= n; i++) {  
        cin >> s;  
        for (int j = 1; j <= m; j++) {  
            a[i][j] = s[j - 1] - '0';  
        }  
    }  

    for (int k = 1; k <= q; k++) {  
        for (int i = 1; i <= n; i++) {  
            cin >> s;  
            for (int j = 1; j <= m; j++) {  
                b[i][j][k] = s[j - 1] - '0';  
            }  
        }  
    }  

    
    for (int i = 0; i < (1 << q); i++) {  
        solve(i);  
    }  

    if (minn == LLONG_MAX) {  
        cout << -1<<"\n";
    } else {  
        cout << minn<<"\n"; 
    }  
    for(int i:vec){
    	cout<<i<<" ";
	}
    return 0;  
}

 喜欢切数组的红

 这题一开始看走眼了,我以为只需要去让数组划分成三个相等的部分(我记得在cf上做过一个相似的,我说这个我熟啊)然后就错了一部分,没想到竟然是因为每个划分中都要有一个正数

因此我们可以用一个额外的辅助数组,去判断前两个部分的不同划分和以及后两个之间的不同划分,只有为正数的时候才去统计辅助数组,负数直接去继承,即可摆脱负数的困扰

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int a[200005];
int pre[200005];//前缀和数组
int cnt[200005];//到i这个位置,前面出现了多少次sum/3这个大小的次数
int num=0;
int ans=0;
signed main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		pre[i]=pre[i-1]+a[i];
	}
	int sum=pre[n];
	if(sum%3!=0)
	{
		cout<<0<<"\n";
	}
	else
	{
		for(int i=1;i<=n;i++)
		{
			if(a[i]>0)
			{
				cnt[i]=num;
			}
			else
			{
				cnt[i]=cnt[i-1];
			}
			if(pre[i]==sum/3)
			{
				num++;
			}
			else if(pre[i]==(sum/3)*2)
			{
				ans+=cnt[i];
			}
		}
		cout<<ans<<"\n";
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值