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.在家里写的,氛围和环境可能要轻松舒适些,到考场可能就没这么多分了
还是有很多东西不会,思维能力也不是很强
以后会争取敢上来的

浙公网安备 33010602011771号