ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022牛客多校7.23

2022-07-24 21:35:26  阅读:103  来源: 互联网

标签:tmp int 多校 7.23 牛客 while maxn include define


A B C D E F G H I J K L M 总题数 通过题数
! ! O O ! O 12 3
Ø Ø O Ø Ø O Ø O 12 ?

赛后总结

G

证明见《离散数学》鸽巢原理
思想是分成\(\sqrt (n)\)个长度不超过\(\sqrt (n)\)的单增子序列,每个子序列按第一位数,从大到小排列

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,T; 
int main(){
	cin>>T;
	while(T--){
		cin>>n;
		int cnt=1;
		while(cnt*cnt<n)cnt++;
		for(int i=cnt;i>=1;i--)
			for(int j=i;j<=n;j+=cnt)
				printf("%d ",j);
		puts("");
	}
	return 0;
}
J

题意是求一个大系数二元二次函数的最小值(保证最小值存在)。
最值的求法只需用到两次二次函数最值,(每次削减一个变量)
若按此法,求解时会炸long double的精度,需要用__float128

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
__float128 A,B,C,D,E,F;
const int maxn=1e5+1000;
int n;
int a[maxn];
inline void read(int &x){
	x=0;int fl=1;char tmp=getchar();
	while(tmp<'0'||tmp>'9')fl=tmp=='-'?-fl:fl,tmp=getchar();
	while(tmp>='0'&&tmp<='9')x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
	x=x*fl;
}
signed main(){
//	freopen("std.txt","r",stdin);
	int T;cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++)
			read(a[i]);
		A=B=C=D=E=F=0;
		for(int i=1;i<=n;i++){
			A+=i*i,C+=2*i,D+=-2*i*a[i],E+=-2*a[i],F+=a[i]*a[i];
		}
		B=n;
		__float128 x,y,z;
		x=(-C/A*C/4+B),y=-C/A*D/2+E,z=F-D/A*D/4;
		long double ans=z-y/x*y/4;
		printf("%.12Lf\n",ans);
	}
	return 0;
}

为了防止精度爆炸,也可以直接用最小二乘法求线性回归(大概是出题思路)

  LD sx = 0, sxx = 0, sy = 0, sxy = 0;
  loop(i, 1, n) {
      sx += i;
      sxx += (LD)i * i;
      sy += a[i];
      sxy += (LD)i * a[i];
  }
  LD bb = (n * sxy - sx * sy) / (n * sxx - sx * sx);
  LD aa = (sxx * sy - sx * sxy) / (n * sxx - sx * sx);

  LD res = 0;
  loop(i, 1, n) {
      LD d = a[i] - (bb * i + aa);
      res += d*d;
  }
  printf("%.8Lf\n", res);
L

这题是队友做的,滚动数组优化空间

赛后补题

K

给一个初始括号串,和最终合法括号串的长度。问合法括号串的个数。
接受\(O(n^3)\)的复杂度
比赛时没仔细算复杂度,以为\(O(n^3)\)不可做。另外受到上次杭电比赛的影响,以为是区间dp。
仍需加强对dp的练习。
不考虑和初始括号串的lcs。那么合法括号串个数可以用g(i,j)数组来求,i->确定括号串的位数,j->左括号比右括号多的个数(右比左多则非法)
定义f(i,j,k)表示,确定合法串的前i位,左比右多k个,lcs至少为j位的状态的个数。

#include<bits/stdc++.h>
#define int unsigned int
using namespace std;
const int maxn=201;
const int mod=1e9+7;
int n,m;
int f[maxn][maxn][maxn];
char s[maxn];
signed main(){
	int T;cin>>T;
	while(T--){
		memset(f,0,sizeof f);
		f[0][0][0]=1;
		cin>>m>>n;
		scanf("%s",s+1);
		for(int i=1;i<=n;i++){
			for(int j=0;j<=i&&j<=m;j++)
				for(int k=0;k<=i;k++){
					printf("(%d,%d,%d): ",i,j,k);
					if(k){
						if(j&&s[j]=='(')f[i][j][k]=f[i-1][j-1][k-1],printf(">(%d,%d,%d)",i-1,j-1,k-1);
						else f[i][j][k]=f[i-1][j][k-1],printf(">(%d,%d,%d)",i-1,j,k-1);
					}
					if(j&&s[j]==')')f[i][j][k]+=f[i-1][j-1][k+1],printf("+(%d,%d,%d)",i-1,j-1,k+1);
					else f[i][j][k]+=f[i-1][j][k+1],printf("+(%d,%d,%d)",i-1,j,k+1);
					puts("");
					f[i][j][k]%=mod;
				}
		}
		cout<<f[n][m][0]<<endl;
	}
	return 0;
}
D

有向图上,找最大的系数w,使得边权均除去w后不存在边权相乘大于1的有向环。
这题比赛场上是另外两位队友负责,思路都是对的,就是没有注意处理好精度问题
首先w是一个二分答案,找环的过程可以用和找负环类似的做法,进队n次以上则环存在。
但若环的过于大,可能会导致dist数组溢出。
处理方式是对边权和w取log,把乘法转换为加法。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
#define SZ(x) ((int)(x).size())
#define mp make_pair
#define fi first
#define se second
#define all(x) x.begin(),x.end()
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef double db;
typedef long long ll;
const ll mod=1e9+7;
template<typename T>
inline void read(T &x){
	x=0;T fl=1;char tmp=getchar();
	while(tmp<'0'||tmp>'9')fl=tmp=='-'?-fl:fl,tmp=getchar();
	while(tmp>='0'&&tmp<='9')x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
	x=x*fl;
}
const int maxn=1100;
int n,m;
vector<pair<int,long double>>g[maxn];
long double dist[maxn];
int cnt[maxn];
bool inq[maxn];
bool check(long double w){
	queue<int>q;
	for(int i=1;i<=n;i++){
		dist[i]=cnt[i]=0,inq[i]=1;
		q.push(i);
	}
	while(!q.empty()){
		int u=q.front();q.pop(),inq[u]=0;
		cnt[u]++;
		if(cnt[u]>n)return 0;
		for(auto r:g[u]){
			if(dist[r.fi]<dist[u]+r.se+w){
				dist[r.fi]=dist[u]+r.se+w;
				if(!inq[r.fi]){
					q.push(r.fi);
					inq[r.fi]=1;
				}
			}
		}
	}
	return 1;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		long double a,c;
		int b,d;
		scanf("%Lf %d %Lf %d",&a,&b,&c,&d);
		c=log(c/a);
		g[b].pb(mp(d,c));
	}
	long double l=0,r=1,mid,ans;
	while(r-l>=1e-8){
		mid=(l+r)/2;
		if(check(log(mid)))l=mid,ans=mid;
		else r=mid;
	}
	printf("%.10Lf\n",ans);
	return 0;
}

标签:tmp,int,多校,7.23,牛客,while,maxn,include,define
来源: https://www.cnblogs.com/xyc1719/p/16514487.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有