Codeforces Round #689 (Div. 2, based on Zed Code Competition)

A. String Generation

签到

  • 题设:T个样例下,每次给一对N和K(1≤k≤n≤1000),分别代表答案字符串的长度,和答案字符串中最长的回文子序列长度。规定:答案字符串只能用‘a’,‘b’,‘c’三种字符。输出任意符合要求的字符串。
  • 思路:k大于等于1,让整个答案字符串最长的回文子序列长度为1即可,那么直接N长度下,循环输出‘a’,‘b’,‘c’即可。

B. Find the Spruce

动态规划

  • 题设:T个样例下,每次输入n,m(1≤n,m≤500),和一张n×m的图,求这张图中可构成多少次云杉树。这里的云杉树可通俗化为:由数行构成,首行为一个星号,接下来每行星号长度增加2的轴对称“金字塔形”。
  • 思路:最大500×500的图,正序暴力遍历不可取。
    先对图进行处理,简化变成二维数组,有星号的位置标记为1。
    再考虑逆向思维,倒序从下往上遍历,对是否构成最小的二层金字塔进行动态规划状态转移,并将当前位置累加进最后答案中。
    状态转移方程:
    dp【i】【j】= min(dp【i+1】【j】,min(dp【i+1】【j-1】,dp【i+1】【j+1】))+1;
    ——AC代码:
#include<bits/stdc++.h>
#define ll long long
#define SC(a) scanf("%d",&a)
#define mem(a,n) memset(a,n,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
priority_queue <int,vector<int>,less<int> > QM;
const int INF= 0x3f3f3f3f;
const int maxn= 2e5+5;
int n,m,dp[505][505];

int main()
{
	IOS;
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		mem(dp,0);
		char c;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				cin>>c;
				if(c=='*')	dp[i][j]=1;
			}
		ll ans=0;
		for(int i=n;i>=1;i--)
		{
			for(int j=1;j<=m;j++)
			{
				if(dp[i][j])
				{
					dp[i][j] = min(dp[i+1][j],min(dp[i+1][j-1],dp[i+1][j+1]))+1;
					ans += dp[i][j];
				}
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

C. Random Events

思维 数学

  • 题设:T个样例下,每次给定一对n,m(1≤n,m≤105),和长度为n的数组a【i】。然后是m个概率事件,每个事件有两个值,r和p,分别代表,此事件将会对数组a中下标【1,r】的元素进行自动升序排列,和这个事件发生的概率p。求:所有事件下,数组变成完全升序的概率。
  • 思路:根据样例推断和题意理解易知:
    1.若存在这样一个事件,只执行这它后数组就完全升序,将它标记。即只要这个特殊事件发生,其他事件任意组合,是否发生都不会影响结果。
    2.找出符合条件的所有特殊事件,若它们都不发生,那么数组必然不会完全升序。那么答案就是:1-这些特殊事件同时不发生的概率(相互独立,累乘)
    3.注意特判,若所有事件都是特殊事件,答案为1。若特殊事件总数为0,答案为0。
    ——AC代码:
#include<bits/stdc++.h>
#define ll long long
#define SC(a) scanf("%d",&a)
#define mem(a,n) memset(a,n,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
priority_queue <int,vector<int>,less<int> > QM;
const int INF= 0x3f3f3f3f;
const int maxn= 2e5+5;

int n,m,a[maxn];
bool vis[maxn];
struct node
{
	int r;
	double p;
}op[maxn];
void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)	cin>>a[i],vis[i]=0;
	for(int i=1;i<=m;i++)	cin>>op[i].r>>op[i].p;
	int cnt=0;
	for(int i=n;i>=1;i--)
	{
		vis[i]=1, cnt++;
		if(a[i]!=i)	break;
	}
	if(cnt==n)
		cout<<"1.000000"<<endl;//特判 
	else
	{
		int flag=0;
		double ans=1;
		for(int i=m;i>=1;i--)
		{
			int num=op[i].r;
			if(vis[num]==1)
			{
				flag=1;
				ans*=(1-op[i].p);
			}
		}
		if(flag)
			printf("%.6lf\n",1-ans);
		else
			cout<<"0.000000"<<endl;//特判 
	}
}
int main()
{
	//IOS;
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_45928596

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值