2019江西省省赛补题报告

K:签到,解方程

一开始直接n方暴力,一直wa,可能是数据范围给错了,不清楚。
改成解方程就可以了

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long x,y;
	while(cin >> x >> y)
	{
		long long a = (x+y)/2;
		long long b = (x-y)/2;
		cout << a*b << endl;
	}
	return 0;
}

F:签到题2,给你一个字符串,求从中选取字母构成avin的概率。

其实就是统计一下a,v,i,n的个数,之后概率相乘即可,分数化简gcd

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n;
	while(cin >> n)
	{

	string s;
	cin >> s;
	int numa = 0;
	int numv = 0;
	int numi = 0;
	int numn = 0;
	for(int i = 0; i < s.length(); i++)
	{
		if(s[i] == 'a')
		{
			numa++;
		}
		if(s[i] == 'v')
		{
			numv++;
		}
		if(s[i] == 'i')
		{
			numi++;
		}
		if(s[i] == 'n')
		{
			numn++;
		}
	}
	if(numa*numv*numi*numn == 0)
	{
		cout << "0/1" << endl;
	}
	else
	{
		int fenzi = 1;
		int fenmu = n*n*n*n;
		fenzi = numa*numv*numi*numn;
		int t = __gcd(fenzi,fenmu);
		fenzi /= t;
		fenmu /= t;
		cout << fenzi << "/" << fenmu << endl;
	}
	}
	return 0;
}

G:憨批暴力题

一开始没看懂英语,其实题意是要求b数组的车都等待相同时间。(即b数组所有的车都+t,t相同)
直接枚举1~1000然后判断会不会相撞即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
const int maxn = 1e3 + 50;
int a[maxn],b[maxn];
int n,m;
int c[maxn];
map<int,int> ma;
int judge(int t)
{
	for(int i = 1; i <= m; i++)
	{
		c[i] = b[i] + t;
		if(ma[c[i]]) return 0; 
	}
	return 1;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	while(cin >> n >> m)
	{
		ma.clear();
		for(int i = 1; i <= n; i++)
		{
			cin >> a[i];
			ma[a[i]]++;
		}
		for(int i = 1; i <= m; i++)
		{
			cin >> b[i];
		}
		int ans = 0;
		for(; ans <= 1001; ans++)
		{
			if(judge(ans)) break;
		}
		cout << ans << endl;
	}
	return 0;
}

D:又是一个暴力题,给你一些条件,求一个数组中满足条件的子序列最长的长度

根据题目中对子序列的要求可以知道:子序列内只有两种数字,交替出现。
首先预处理原数组,记录每个数字出现的所有位置。
那么我们可以在1~c的范围内n方暴力枚举这两个数字。
之后我们就去计算这两个数字i,j能构成最长的子序列即可。

假设先i后j,(因为枚举两个数是n方,所以不用交换位置了)那么我们先取第一个i的位置pos,之后从j中找到第一个位置大于pos的j,位置是pos1,之后再从i里面找到第一个大于pos1的i位置为pos2。以此类推可以得到最长子序列的长度。
n方取最大值即可。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e5 + 50;
vector<int> pos[105];
int n,c;
int solve(int i, int j)
{
	if(pos[i].empty() || pos[j].empty()) return 0;
	int res = 0;
	int posi = 0;
	int t = 0;
	int lastj = 0;
	for(t = 0; t < pos[j].size(); t++)
	{
		if(posi >= pos[i].size()) break;
		if(pos[j][t] > pos[i][posi])
		{
			res += 2;
		//	if(i == 1 && j == 2)
		//	cout << pos[i][posi] << " " << pos[j][t] << endl;
			lastj = pos[j][t];
			while(pos[i][posi] < pos[j][t] && posi < pos[i].size())
			{
				posi++;
			}
		}
		else
		{
			continue;
		}
	}
	int numa = pos[i].size() - 1;
	//cout << i << " " << numa << endl;
	int lasti = pos[i][numa];
	if(lasti > lastj) res++;
	return res;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	while(cin >> n >> c)
	{
		for(int i = 1; i <= c; i++)
		{
			pos[i].clear();
		}
		for(int i = 1; i <= n; i++)
		{
			int a;
			cin >> a;
			pos[a].push_back(i);
		}
		int ans = 0;
		for(int i = 1; i <= c; i++)
		{
			for(int j = 1; j <= c; j++)
			{
				if(i != j)
				{
					ans = max(ans,solve(i,j));
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}

注意:如果vector的长度为0,不可以调用size(),会终止导致程序无输出,需要特判vector为空的情况。
——————————————————————————————————————————————————
队友写的I,J,自己补上

I:求n个小数,在小数点后第三位四舍五入,误差的总和。

用字符串存小数,在小数点后取三位,计算四舍五入即可。

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
	int n;
	while(cin >> n)
	{
		double ans = 0;
		for(int i = 1; i <= n; i++)
		{
			string s;
			cin >> s;
			long long a = 0;
			for(int i = 0; i < s.length(); i++)
			{
				if(s[i] == '.')
				{
					a = (s[i+1]-'0')*100 + (s[i+2]-'0')*10 + (s[i+3]-'0');
				}
			}
		//得到小数点后三位 
			long long b = a;
			if(a % 10 >= 5)
			{
				b = a;
				b -= (a % 10);
				b += 10;
			}
			else
				b -= (b % 10);
			double sum = b - a;
		//	cout << a << " " << b << endl;
			ans += sum / 1000.0;
		}
		printf("%.3lf\n",ans);
	}
	return 0;
}

J:求数组的最小公倍数,之后分配数目构成最小公倍数的倍数即可。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e3 + 50;
long long a[maxn];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n,m;
	while(cin >> n >> m)
	{
		vector<long long> ans;
		for(int i = 1; i <= n; i++)
		{
			cin >> a[i];
		}
		ans.push_back(0);
		long long t = 1;
		for(int i = 1; i <= n; i++)
		{
			t = t / __gcd(t,a[i]) * a[i];
		}
		long long sum = 0;
		for(int i = 1; i <= n; i++)
		{
			long long num = t / a[i];
			sum += num;
			ans.push_back(num);
		}
		if(m % sum != 0)
		{
			cout << "No" << endl;
		}
		else
		{
			cout << "Yes" << endl;
			int p = m / sum;
			for(int i = 1; i <= n; i++)
			{
				if(i != n)
				cout << ans[i]*p << " ";
				else cout << ans[i]*p << endl;
			}
		}
	}
	return 0;
}

——————————————————————————————————————————————————

H:给你一个区间1~n,从中选取两个区间,求两区间相交的概率

RNG NB!

假设我选择的两个区间:[a1,b1]与[a2,b2]。
那么两个区间不相交的情况为:b1 < a2 或者 b2 < a1,满足其中一个,即可不相交。
得到: min(b1,b2) < max(a1,a2)即可。
那么我们去选择 min(b1,b2) 与 max(a1,a2),简称b和a。

总共有nn种选择,其中b<a,有(n-1) n / 2种
那么得到:不相交的概率 = 1 - 相交 = 1 - (n-1)* n / 2 / (n*n) = (n+1)/(2n)。

快速幂取模,费马小定理

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int mod = 1e9 + 7;
long long quickPower(long long x, long long y)//快速幂加取模 
{ 
    long long result = 1; // 定义答案 
    while (y > 0) // 当指数大于 0 时进行幂运算
    {
        if (y & 1) // y 和 1 做与运算,相当于对 2 求模
        {
            result = (result * x) % mod;// 如果 y 为奇数,则结果只乘一个 x
        }
        x = x * x % mod;  // x 乘二次方,下次使用
        y = y >> 1; // y 右移一位,相当于除以 2
    }
    return result % mod; // 返回结果 
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long n;
	while(cin >> n)
	{
		long long ans = quickPower((2*n),mod-2);
		ans *= (n+1);
		ans %= mod;
		cout << ans << endl;
	}
	return 0;
}

B:概率dp

dp[i]表示从i走到i+1的期望消耗

在i走到i+1时,分情况讨论:

  1. 没有丢: 1-p
  2. 丢了,并且走到n才发现: p * 2 * (1-q)^(n-i) * (n-i) 一直没有发现,走到n,再回到i
  3. 丢了,没走到n就发现了:需要枚举i后x步发现丢失了。 2 * p * q * (1-q)^x * x, x从0枚举到n-i-1
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 1e5 + 50;
double dp[maxn];
//表示从i走到i+1时的期望 
double sum[maxn];
double q1[maxn];
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	long long l;
	double p,q;
	while(cin >> l >> p >> q)
	{
		sum[0] = 0;
		q1[0] = 1;
		for(int i = 1; i <= l; i++)
		{
			q1[i] = q1[i-1] * (1-q);
			sum[i] = sum[i-1] + q1[i]*i;
		}
		double ans = 0;
		for(int i = 0; i < l; i++)
		{
			ans += (1 - p + 2*p*q1[l-i]*(l-i) + 2*p*q*(sum[l-i-1])) / (1-p);
		}
		printf("%.6lf\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值