头更更大
这个10月完就要去搞NOIP了。。。
10月30天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。
boomshakalaka。。。第三题写炸。。。
第一题dfs(?)回溯妙解(再加一个预判)。。
第三题。。本来我顺手甩了一个最大生成树上去以为我最多骗个30分。。结果是正解??但是因为并查集没有总结路径GG了只有70分。。。orz
不过这样排名还看着可以。。但是要是我200分的话就第4了。。。
最无语的是我用了两个小时做的第二题最后考完了也没有凑出正解。。。T_T
TEST 5 for NOIP(170/300)
鱼群分裂(100/100)
题目描述
豆豆养了一群鳕鱼。这些鳕鱼在收到惊吓的情况下会分成很多小鱼群四处逃窜。豆豆观察到这些鳕鱼鱼群分裂很有意思。如果当前的鱼群有 N 只鱼,并且可以分裂成两个鱼群使得这两个鱼群中的鱼的数量差恰好为 K ,那么这群鱼就会分裂成两群数量相差 K 的鱼群,否则就不会分裂。(就是这么奇怪)
豆豆想知道最终会分裂成多少群鱼?
输入格式
第一行两个整数 N, K 代表初始时的第一群鱼的数量和数值 K ;
输出格式
输出一个整数表示最终形成的鱼群数量。
样例数据 1
输入 [复制]
6 2
输出
3
备注
【样例说明】
6 分裂成 4 和 2 ,4 分裂成 1 和 3 。
【数据范围】
对于 50% 的数据,K 为奇数;
对于 100% 的数据,N≤10^9,K≤1000。
MY/STD.CPP
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int dfs(int t,int k)
{
if(t%2==k%2&&t>k)
return dfs((t+k)/2,k)+dfs((t-k)/2,k);
else return 1;
}
int n,k;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
cin >> n >> k;
if(n%2==k%2&&k==0)cout<<n<<endl;
else cout<<dfs(n,k)<<endl;
}
简单回溯即可。
跑步
题目描述
企鹅国正在举办全面运动会,第一项比赛就是跑步。N 个人在圆形跑道上跑步,他们都有各自的速度和起点。但这个跑步规则很奇怪,当两个人相遇的时候编号较小的就会出局,当场上剩下最后一个人的时候跑步就结束了。豆豆想知道多长时间游戏会结束?
输入格式
第一行一个整数 T 表示数据组数;
每组数据的第一行是两个整数 N 和 L ,表示参赛人数以及跑道长度。
接下来一行有 N 个不同的整数 Di,表示每个人的起点。
接下来一行有 N 个不同的整数 Vi,表示每个人的跑步速度,如果速度为负数,就是在反着跑。
输出格式
对于每组数据,以最简分数形式表示游戏结束的时间。
样例数据 1
输入 [复制]
2
2 4
0 2
3 2
10 100
56 89 62 71 7 24 83 1 47 52
9 -16 34 -38 47 49 -32 17 39 -9
输出
2/1
37/7
备注
【数据范围】
对于 30% 的数据,2≤n≤100, 1≤L≤200;
对于 60% 的数据,2≤n≤10^3。
对于 100% 的数据,2≤n≤10^5,T≤5, 1≤L≤10^9, 0≤Di< L, 0≤|Vi|≤10^9;
题太魔性不想看了(看得我想睡觉)
STD.CPP
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=1e5+5,INF=1e9+5;
int T,n,L;
struct node
{
int s,v,l,r,id;
inline friend bool operator < (const node &a,const node &b)
{return a.s<b.s;}
}a[N];
struct meet
{
int x,y;
double t;
inline friend bool operator < (const meet &a,const meet &b)
{return a.t>b.t;}
};
priority_queue<meet>q;
bool del[N];
int gcd(int a,int b)
{
return !b?a:gcd(b,a%b);
}
double gettime(int x,int y)
{
if(a[x].s>a[y].s)swap(x,y);
if(a[x].v>a[y].v)return (a[y].s-a[x].s)*1.0/(a[x].v-a[y].v);
return (L-(a[y].s-a[x].s))*1.0/(a[y].v-a[x].v);
}
void W(int x,int y)
{
int dis,dv,r;
if(a[x].s>a[y].s)swap(x,y);
if(a[x].v>a[y].v)
{
dis=a[y].s-a[x].s,dv=a[x].v-a[y].v;
r=gcd(dis,dv);
dis/=r,dv/=r;
}
else
{
dis=L-(a[y].s-a[x].s),dv=a[y].v-a[x].v;
r=gcd(dis,dv);
dis/=r,dv/=r;
}
cout<<dis<<"/"<<dv<<'\n';
}
int main()
{
//freopen("run.in","r",stdin);
//freopen("run.out","w",stdout);
T=getint();
while(T--)
{
n=getint(),L=getint();
memset(del,false,sizeof(del));
while(!q.empty())q.pop();
for(int i=1;i<=n;i++)a[i].id=i,a[i].s=getint();
for(int i=1;i<=n;i++)a[i].v=getint();
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
a[i].l=i-1,a[i].r=i+1;
a[1].l=n,a[n].r=1;
for(int i=1;i<=n;i++)
q.push((meet){i,a[i].r,gettime(i,a[i].r)});
for(int i=1;i<=n-2;i++)
{
while(del[q.top().x]||del[q.top().y])q.pop();
int x=q.top().x,y=q.top().y,z;
q.pop();
if(a[x].id<a[y].id)swap(x,y);
del[y]=true;
if(y==a[x].l)z=a[y].l,a[x].l=z,a[z].r=x;
else z=a[y].r,a[x].r=z,a[z].l=x;
q.push((meet){x,z,gettime(x,z)});
}
while(del[q.top().x]||del[q.top().y])q.pop();
W(q.top().x,q.top().y);
}
return 0;
}
拆墙(70/100)
题目描述
地主的傻儿子豆豆家很大很大,由很多个区域组成。其中有不少封闭的区域,豆豆觉得很不爽于是决定拆墙,把家打通使得他可以访问到每一个区域(包括家外面无限大的区域)。我们用 N 个端点和 M 条边来描述豆豆的家。第 i 个端点的坐标为(xi,yi),第 i 条边连接端点 Ai 和 Bi,拆除所需要花费的力气为 Ci 。保证所有边只在端点相交,也就是这是一个平面图,也没有重边和自环。
现在豆豆想知道他最少一共需要花费多少力气?
输入格式
第一行一个整数 T 表示数据组数。
每组数据第一行两个整数 N,M 。
接下来 N 行每行两个整数 Xi 和 Yi。
接下来 M 行每行三个整数 Ai,Bi,Ci。
输出格式
每组数据输出两个整数表示最少拆除的墙的数量和拆墙最少需要多少的力气。注意所有墙可能不互相连通。
样例数据 1
输入 [复制]
1
4 4
-1 -1
-1 1
1 1
1 -1
1 2 1
2 3 2
3 4 1
4 1 2
输出
1 1
备注
【数据范围】
对于 30% 的数据,N,M≤10,T=10;
对于 70% 的数据,N≤5000, M≤10000,T=1;
对于 100% 的数据,N≤100000;M≤200000;ΣN≤300000;ΣM≤500000;|xi|,|yi|≤100000;0≤wi≤10000,T=3。
坐标没任何卵用(然而害得一个工程学大佬打了450多行最后没打完),直接扔一个最大生成树就行
永远要把模板打正确。不然很揪心。
MY/STD.CPP
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
int u,v,val,cnt=0;
int n,m;
bool visit[100005];
struct node{
int u,v,val;
}side[100005*2];
bool comp(node a,node b){return a.val>b.val;}
int fa[100005*2];
int getfa(int x)
{
return fa[x]==x?x:fa[x]=getfa(fa[x]);//<=永远记得压缩路径啊!!!
}
int t;
int ans1;
long long sum,ans2;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//freopen("wall.in","r",stdin);
//freopen("wall.out","w",stdout);
cin >> t;
while(t--)
{
sum=0;ans1=0;ans2=0;cnt=0;
cin >> n >> m;
for(int i=1;i<=n;i++){cin>>u>>v;}
for(int i=1;i<=m;i++)
{
cin >> u >> v >> val;
side[++cnt].u = u;
side[cnt].v = v;
side[cnt].val = val;
sum += val;
fa[u]=u;fa[v]=v;
}
sort(side+1,side+cnt+1,comp);
for(int i=1;i<=cnt;i++)
{
if(getfa(side[i].u)!=getfa(side[i].v))
{
fa[getfa(side[i].u)] = side[i].v;
ans2 += side[i].val;
ans1 += 1;
}
}
cout << m-ans1 << " " << sum-ans2 << endl;
}
}
感想
多刷Dp多做题,多背模板多总结。
模板不能有错!!!
NOIP初赛
2017.10.13.复习复习,明早还要考次试(曾老叫的orz),下午初赛。
在此感谢帮我们凑人数的班上24个人。
然后感谢在竞赛道路上帮助过我的老师和同学。
虽然还不是最后的复赛,但还是要认真考,毕竟只有这一次机会,千万大意不得。。
最后。。希望我能考上省一吧。。