noip2018自测报告

昨天和今天测了一下前年noip tg的题

100+80+20+60+45+0=305pts

应该是大众分了。。刚好压前年我省1=线。。

我还是太弱了/kk

提交的代码:

D1T1:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5;
int n,a[N],ans;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	  scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	  if(a[i]-a[i-1]>0)ans+=a[i]-a[i-1];
	printf("%d",ans);
	return 0;
}

D1T2:

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=105;
const int M=3e6+10;
int T,n,a[N],dp[M],ans,sum;
void clear(){
	memset(dp,0,sizeof(dp));
	dp[0]=1;ans=n;
}
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);clear();
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			sum+=a[i];
		}
		sort(a+1,a+n+1);
        for(int i=1;i<=n;i++){
            if(dp[a[i]]){ans--;continue;}
            for(int j=a[i];j<=sum;j++)
                dp[j]|=dp[j-a[i]];
        }
		printf("%d\n",ans);
	}
	return 0;
}

D1T3:

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=5e5+10;
int n,m,tot=0,vis[N],ans,id;
int to[N],val[N],pre[N],now[N];
void add(int x,int y,int z){
	pre[++tot]=now[x];
	to[tot]=y,val[tot]=z;
	now[x]=tot;
}
void dfs(int x,int fk){
	vis[x]=true;
	if(fk>=ans){id=x;ans=fk;}
	for(int i=now[x];i;i=pre[i]){
		int y=to[i];
		if(vis[y])continue;
		dfs(y,fk+val[i]);
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,u,v,l;i<n;i++){
		scanf("%d%d%d",&u,&v,&l);
		add(u,v,l);add(v,u,l);		
	}
	dfs(1,0);
	memset(vis,0,sizeof(vis));ans=0;
	dfs(id,0);
	printf("%d",ans);
	return 0;
}

 T1:

看到T1后我们可以画个图:

我们把深度看成高度,分成了$max { a[i] } $层

很显然答案就是每一层被分开的区间数的总和

 Subcode:

for(int h=1;h<=MaxA;h++)
	for(int i=1;i<=n;i++)
		if(a[i]>=h&&a[i-1]<=h)ans++;

时间复杂度为$O(n$\times$max{a[i]})$;

我们再看一下

其实每一次的答案的累加只与相邻的两项有关

而且对答案的贡献就是$a[i] - a[i-1] (a[i] > a[i-1] )$

时间复杂度$O(n)$;

T2:

猜结论的

已经能被其他钱币凑出来的就不用了

这有dalao的数学证明:

https://www.luogu.com.cn/blog/lymoe/solution-p5020

T了20分,交的时候没把sum换成mx,因为答案只关心值域以内的

T3:

有很好拿的55分的暴力

(1).求树上距离最长的两个点(其实就是树的直径)

(2).一条链

(3).菊花图

我只拿了(1)的暴力20

先求出距离1最远的点,然后以那个点作为起点,再找一个最远的点

(2)一段区间的二分答案,但是我是懒鬼就没打了。。

(3)把边权排序,计算再比较就行了

正解是二分答案+我看不懂的操作

我是大椈偌,不会。

-------------------------------------------------------------------------------------------------------------------------

D2T1:

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=5e3+10;
vector<int>G[N];
int n,m,path[N],lst,cnt;
bool vis[N];
void dfs(int x){
	vis[x]=true;path[++cnt]=x;
	for(int i=0;i<G[x].size();i++){
		int y=G[x][i];
		if(vis[y])continue;
		dfs(y);
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	for(int i=1;i<=n;i++)
		sort(G[i].begin(),G[i].end());
	if(m==n-1){
		dfs(1);
		for(int i=1;i<=cnt;i++)
			cout<<path[i]<<" ";
		return 0;
	}
	return 0;
}

D2T2:

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
long long ans,n,m;
int main(){
	scanf("%lld%lld",&n,&m);
	if(n==2&&m==2)ans=12;
	if(n==3&&m==3)ans=112;
	if(n==5&&m==5)ans=7136;
	if(n==2&&m==3)ans=36;
	if(n==3&&m==2)ans=36;
	if(n==2){
		ans=4;
		for(int i=2;i<=m;i++)
			ans=ans*3%mod;
	}
	printf("%lld",ans);
	return 0;
} 

D2T3:没写(看到题面长就。。。了)

 T1:

n=m-1,且所有点能互相到达。

前50分很明显是个树

要使字典序最小,只需要将边权排序,然后dfs就van了

n==m就是基环树

我太菜了,不会。。

T2:

1~4的数据直接算就行了

下面是我对n=2的分析

当n=2时 其实只有两个路径

一直R的那一条字典序大于一直D的那个

 

 同样颜色是两条路线同时到达的,此时要使s(1)>=s(2)

在同一位上有三种情况:

(1,0)(1,1)(0,0)

所以每一对颜色对答案的贡献是3

 

 起点和终点取0,1任意一值都行

所以答案就等于$4*3^{(m-1)}$

鉴于m比较小,就不需要快速幂了

正解其实就是对这种思路的升级版

T3:

题面还没看。。

留个坑等期中考完再弄吧

 

 

总结

1.人还是太懒了,有些暴力分觉得会写或者不想写就没打了。。

2.在家里写的,氛围和环境可能要轻松舒适些,到考场可能就没这么多分了

还是有很多东西不会,思维能力也不是很强

以后会争取敢上来的

posted @ 2020-06-20 17:31  Isenthalpic  阅读(6)  评论(0编辑  收藏  举报