2022牛客暑期多校训练营2

比赛链接

2022牛客暑期多校训练营2

给定 \(m\) 个物品合成的方式,求一个最大的合成损耗参数 \(w\) ,使得所有
物品都无法通过无限合成的方式无限获得

解题思路

spfa,二分

显然,如果 \(w\) 越小,其生成的材料越少,其越能满足题目要求,故可二分 \(w\),一个点如果经过一个环后其参数反而变大,则其一定不满足要求,故可用 \(spfa\) 找最长路的同时判断环,另外由于乘积容易爆 \(double\),需要对路径取对数,即将乘法转换为加法

设二分的循环次数为 \(k\),则:

  • 时间复杂度:\((knm)\)

代码

// Problem: Link with Game Glitch
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/33187/D
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2005;
int n,m,cnt[N];
double d[N];
vector<pair<int,double>> adj[N];
bool v[N];
bool ck(double w)
{
	memset(cnt,0,sizeof cnt);
	memset(v,0,sizeof v);
	memset(d,0,sizeof d);
	queue<int> q;
	for(int i=1;i<=n;i++)q.push(i),v[i]=true;
	while(q.size())
	{
		int x=q.front();
		q.pop();
		v[x]=false;
		for(auto &t:adj[x])
		{
			int y=t.fi;
			double ww=t.se;
			if(d[y]<d[x]+ww+w)
			{
				cnt[y]=cnt[x]+1;
				if(cnt[y]>n)return false;
				d[y]=d[x]+ww+w;
				if(!v[y])q.push(y),v[y]=true;
			}
		}
	}
	return true;
}
int main()
{
    help;
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
    	double a,c;
    	int b,d;
    	cin>>a>>b>>c>>d;
    	adj[b].pb({d,(double)log(c/a)});
    }
    double l=0,r=1;
    for(int i=1;i<=100;i++)
    {
    	double mid=(l+r)/2;
    	if(ck(log(mid)))l=mid;
    	else
    		r=mid;
    }
    cout<<l;
    return 0;
}

已知括号序列 \(a\) 是一个长度为 \(m\) 的合法括号序列 \(b\) 的子序列,求可能
的序列 \(b\) 的数量

解题思路

dp

  • 状态表示:\(f[i][j][k]\) 表示 \(b\) 的前 \(i\) 个字符,用了 \(a\) 的前 \(j\) 个字符,且左括号比右括号多 \(k\) 个的方案数

状态转移:当母序列 \(i\) 位表示左括号时,如果子序列 \(j\) 位为左括号,则其一定要匹配上,\(\color{red}{为什么?}\)例如母序列为()(),子序列为(),则此时母序列表示前面匹配所有子序列的一种情况,即 ()**的一种情况,如果遇到一定要匹配的反而不匹配则会有重复情况,例如对于()**(*)*两种情况,如果前面匹配了即第二个不会出现())*的情况,达到了去重的要求

  • 时间复杂度:\(O(m^2n)\)

代码

// Problem: Link with Bracket Sequence I
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/33187/K
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=205,mod=1e9+7;
int t,n,m,f[N][N][N];
char s[N];
int main()
{
    help;
    for(cin>>t;t;t--)
    {
    	cin>>n>>m>>(s+1);
    	for(int i=0;i<=m;i++)
    		for(int j=0;j<=n;j++)
    			for(int k=0;k<=m;k++)f[i][j][k]=0;
    	f[0][0][0]=1;
    	for(int i=1;i<=m;i++)
    		for(int j=0;j<=min(i,n);j++)
    			for(int k=0;k<=i;k++)
    			{
    				int &t=f[i][j][k];
    				if(j&&s[j]==')')t=(t+f[i-1][j-1][k+1])%mod;
    				else
    					t=(t+f[i-1][j][k+1])%mod;
    				if(k)
    				{
    					if(j&&s[j]=='(')t=(t+f[i-1][j-1][k-1])%mod;
    					else
    						t=(t+f[i-1][j][k-1])%mod;
    				}
    			}
    	cout<<f[m][n][0]<<'\n';
    }
    return 0;
}
posted @ 2022-07-24 18:57  zyy2001  阅读(23)  评论(0编辑  收藏  举报