2019年CCPC-江西省赛部分题解

目录

B - Wave

C - String

D - Traffic

F - Budget

G - Worker

H - Class


B - Wave

题意:

给一个n个整数的序列,整数范围为1~c,求一个子序列满足偶数位上数字相同,奇数位上数字相同,且奇偶位上的数字不同。

输出满足要求的最长子序列的长度。

思路:

简单 DP,设dp[i][j]是以 j 结尾, i 为结尾前一个数字的最长合法 wave,

则有状态转移方程:
dp[i][j]=dp[j][i]+1

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int dp[110][110];
int a[maxn];
int main()
{
    int n,c,x;
    while(cin>>n>>c)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++)
        {
            cin>>a[i];
        }
        int ans=0;
        for(int i=1; i<=c; i++)
        {
            if(a[1]==i)
            {
                dp[a[1]][i]=0;
            }
            else
            {
                dp[a[1]][i]=1;
            }
        }
        for(int i=2; i<=n; i++)
        {
            for(int j=1; j<=c; j++)
            {
                if(a[i]==j)
                    dp[a[i]][j]=0;
                else
                    dp[a[i]][j]=dp[j][a[i]]+1;
                ans=max(ans,dp[a[i]][j]);
            }
        }


        cout<<ans<<endl;
    }
}

C - String

题意:一个长度为n的字符串,每次从字符串中随机取出一个字符(可放回)。取4次,问按照取字符的顺序组成的字符串有多少几率是"avin"?
请输出最简化分数形式。若概率为0,则输出"0/1"。

思路:统计每种字符出现的次数,根据乘法原理计算概率。输出最简化分数形式,求一下分子分母除以其最大公因子。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e3+10;
ll a[maxn];
ll b[maxn];
map<char,int> mp;
int main()
{
    int n;
    while(cin>>n)
    {
        mp.clear();
        string s;
        cin>>s;
        for(int i=0;i<n;i++)
            mp[s[i]]++;
        ll y=n*n*n*n;
        ll x=mp['a']*mp['v']*mp['i']*mp['n'];
        if(x==0) cout<<"0/1"<<endl;
        else
        {
            ll z=__gcd(x,y);
            x/=z;
            y/=z;
            cout<<x<<"/"<<y<<endl;
        }
    }
}

D - Traffic

题意:

有一个十字路口,分为东西方向和南北方向。两个方向在不同的时间点会有车辆经过,如果同一个时间点两个方向都有来车,就会发生交通事故,为了避免事故发生。于是规定,东西方向的车优先行驶,将南北方向的车辆的的通过时间向后推迟(整体推迟),求一个最小推迟时间使得东西方向与南北方向的车辆的通过时间点不会重叠。

思路:

东西方向车辆等待时间a[j],南北方向b[i],我们要找到最小推迟时间ans,使得b[i]+ans=a[j](1\leq i\leq m,1\leq j\leq n)。标记a数组,遍历b数组,如果当前的b[i]+ans会与a中元素相撞,则ans++。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
int a[maxn],b[maxn],vis[maxn];
int main()
{
	int n,m;
	while(cin>>n>>m)
    {
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
		{
			cin>>a[i];
			vis[a[i]]=1;
		}
		for(int i=0;i<m;i++)
		{
			cin>>b[i];
		}
		int ans=0;
		for(int i=0;i<m;i++)
		{
			if(vis[b[i]+ans]==1)
			{
				i=0;
				ans++;
			}
		}
		cout<<ans<<endl;
	}

}

F - Budget

题意:将三位小数四舍五入为两位小数,并判断误差是多少。

思路:字符串输入该数,然后用a[a.length()-1]-'0'对最后一位小数进行判断:

设b为最后一位小数(即小数点后第3位)

(1)如果b<=4,那么答案加上-b*0.001。

 (2)如果b>=5,那么答案加上(10-b)*0.001。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
int a[maxn],b[maxn],vis[maxn];
int main()
{
	int n;
	while(cin>>n)
	{
		string a;
		double sum=0;
		for(int i=0;i<n;i++)
		{
			cin>>a;
			int x=a.length();
			if(a[x-1]-'0'>=5)
			{
				sum+=((10-(a[x-1]-'0'))*0.001);
			}
			else sum-=((a[x-1]-'0')*0.001);
		}
		printf("%.3lf\n",sum);
	}
}


G - Worker

题意:有 n 个车间, m 个工人。在第 i 个车间工作的工人可以完成 a_{i}个任务。请你求出一个分配工人的方案,使得每个车间最后完成的任务总数是相同的。没有方案则输出" NO",可以分配输出“YES”及其每个车间的工人人数。

思路:

各仓库分配人数的比例应为\frac{1}{a_{1}}:\frac{1}{a_{2}}:......:\frac{1}{a_{n}}

很可惜它们不是整数,我们令M=lcm(a_{1},a_{2},......a_{n})(M为数组的最小公倍数)

各仓库分配人数的比例应为\frac{M}{a_{1}}:\frac{M}{a_{2}}:......:\frac{M}{a_{n}}

则第i个仓库需要m*\frac{\frac{M}{a_{i}}}{\sum_{i=1}^{n}\frac{M}{a_{i}}}人,如果该值不是整数,则输出NO。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
ll a[maxn],b[maxn];
ll gcd(int aa,int bb)
{
	return bb==0?aa:gcd(bb,aa%bb);
}
ll lcm(int aa,int bb)
{
	return aa/gcd(aa,bb)*bb;
}
int main()
{
	ll n,m;
	while(cin>>n>>m)
	{
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		ll sum=1;
		ll sum1=0;
		for(ll i=0;i<n;i++)
		{
			cin>>a[i];
			sum = lcm(sum,a[i]);
		}
		for(ll i=0;i<n;i++)
		{
			b[i]=sum/a[i];
			sum1+=b[i];
		}
		if(m%sum1==0)
		{
			cout<<"Yes"<<endl;
			for(ll i=0;i<n;i++)
			{
				if(i==0)
				{
				    cout<<(m/sum1)*b[i];
				}
				else
				{
				    cout<<" "<<(m/sum1)*b[i];
				}
			}
			cout<<endl; 
		}
		else
		{
			cout<<"No"<<endl;
		}
	}
}


H - Class

题意:

思路:

a*(x-a)==a*(a-y)

a=\frac{x+y}{2},b=x-a=\frac{x-y}{2}

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
     int x,y;
     cin>>x>>y;
     cout<<(x*x-y*y)/4<<endl;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值