NOIP2014提高组 自测
闲的慌也是手比较痒了,就打算找NOIP原题做一下,看看自己的水平,虽然大家都说2014年的题水。
日期: 2018.2.25
时间: 7小时
分数:450
对于2014年提高组成绩,高出省一线10分,Rank约为60+
Day1
T1
Solution
打表即可。
#include<cstdio>
using namespace std;
// win 1 dy 2 lose 3
int st[5][5]={{2,3,1,1,3},{1,2,3,1,3},{3,1,2,3,1},{3,3,1,2,1},{1,1,3,3,2}};
int ra[205];
int rb[205];
int main(){
int N,A,B,ansa=0,ansb=0;
scanf("%d%d%d",&N,&A,&B);
for(register int i=0;i<A;++i){
scanf("%d",&ra[i]);
}
for(register int i=0;i<B;++i){
scanf("%d",&rb[i]);
}
for(register int i=0;i<N;++i){
int l = ra[i%A];int r = rb[i%B];
if(st[l][r]==1)ansa++;
if(st[r][l]==1)ansb++;
}
printf("%d %d",ansa,ansb);
return 0;
}
socre:100
T2
emmmm这道题没想出正解,日后待更。
Solution(TLE)
邻接表建图,依次枚举所有点,然后遍历其子节点的子节点。
#include<cstdio>
#define MAXN 200005
#define mod 10007
using namespace std;
inline int read(){
int num=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
return num*f;
}
struct Node{
int v,next;
}G[MAXN<<1];
int head[MAXN]={0};
int w[MAXN];
int N,tot=0;
long long max = -1;
long long sum = 0;
inline void add(int u,int v){G[++tot].v=v;G[tot].next=head[u];head[u]=tot;}
inline void dfs(int fa,int rt){
for(register int i=head[rt];i;i=G[i].next){
int v = G[i].v;if(v==fa)continue;
long long W = (long long)w[fa]*w[v];
if(W>max)max=W;
sum = (sum+W)%mod;
}
}
int main(){
N=read();
for(register int i=1;i<=N<<1;++i)G[i].next=0;
for(register int i=1;i<=N;++i)head[i]=0;
int u,v;
for(register int i=1;i<N;++i){
u=read();v=read();add(u,v);add(v,u);
}
for(register int i=1;i<=N;++i){
w[i]=read();
}
for(register int i=1;i<=N;++i){
for(register int j=head[i];j;j=G[j].next)dfs(i,G[j].v);
}
printf("%lld %lld",max,sum);
return 0;
}
score:70
补充
N个节点N-1条边的无向连通图——树,则可以往此方面去想正解,但是自测时没有想出。
T3
看上去这道题就是个dp,但是技艺不精不会写,所以只能试着去交一个暴力。
Solution (TLE)
对于每一个时刻,都有不点和点i下的操作,则根据此进行爆搜。
#include<cstdio>
#define MAXN 100005
using namespace std;
inline int read(){
int num=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
return num*f;
}
int N,M,K;
int l[MAXN],r[MAXN];
int x[MAXN],y[MAXN];
int map[MAXN];
int maxcnt = 0;
int min = 2147483647;
inline bool dfs(int p,int h,int count,int num){
if(h>M)h=M;
if(h<=0)return false;
if(map[p]!=0){
if(h>l[map[p]]&&h<r[map[p]])count++;
else return false;
}
if(count>maxcnt)maxcnt=count;
if(num>=min)return false;
if(p==N){
min = num;
return true;
}
bool f = false;
if(dfs(p+1,h-y[p],count,num))f = true;
int last = 0;
for(register int i=1;h+i*x[p]<=M;++i){
if(dfs(p+1,h+i*x[p],count,num+i))f = true;
last = i;
}
if(last*x[p]<M)
if(dfs(p+1,h+(last+1)*x[p],count,num+last+1))f = true;
return f;
}
int main(){
int p;
N=read();M=read();K=read();
for(register int i=0;i<N;++i)x[i]=read(),y[i]=read();
for(register int i=1;i<=K;++i){
p=read();map[p]=i;l[i]=read();r[i]=read();
}
bool f = false;
for(register int high = 1;high<=M;++high){
if(dfs(0,high,0,0))f = true;
}
if(f)printf("1\n%d",min);
else printf("0\n%d",maxcnt);
return 0;
}
score:50
DAY1总分:220
DAY 2
T1
Solution
由于数据范围比较小,所以直接选用暴力枚举所有点,然后以此为中心枚举周边即可。
#include<cstdio>
using namespace std;
int map[130][130];
int d,n;
int main(){
for(register int i=0;i<129;++i)
for(register int j=0;j<129;++j)
map[i][j] = 0;
scanf("%d%d",&d,&n);
for(register int i=0;i<n;++i){
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
map[x][y] = k;
}
int ans = 0;
int max = -1;
for(register int i=0;i<129;++i)
for(register int j=0;j<129;++j){
int count = 0;
for(register int x=i-d;x<=i+d;++x)
for(register int y=j-d;y<=j+d;++y){
if(x>128||y>128||x<0||y<0)continue;
count+=map[x][y];
}
if(count==0)continue;
if(count>max){
max = count;
ans = 1;
}
else if(count==max)ans++;
}
printf("%d %d",ans,max);
return 0;
}
score:100
补充:
此题也可以使用前缀和或差分。
T2
Solution
可考虑使用BFS进行找最短路,但是对于节点的排除,可以建反图然后从终点开始BFS,遍历到的节点即为可以直接或间接达到终点的节点。
对于自己出边上的节点判断,可以在反BFS时给访问到的节点的入边节点+1,则代表它多了一个能到达终点的出边节点,最后遍历一下,哪些数目不对,则代表自己存在不能到达终点的出边节点。
#include<cstdio>
#define MAXN 10005
#define MAXM 200005
using namespace std;
inline int read(){
int num=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
return num*f;
}
struct SIZE{
int v,next;
}G[MAXM],g[MAXM];
int head1[MAXN];
int head2[MAXN];
struct NODE{
int count,size,vis;
}Node[MAXN];
int queue[MAXN];
int N,M;
int tot=0;
int s,t;
inline void add(int u,int v){
G[++tot].v=v;G[tot].next=head1[u];head1[u]=tot;
g[tot].v=u;g[tot].next=head2[v];head2[v]=tot;
}
inline void BFS1(){
Node[t].vis=1;
queue[1]=t;
int l = 1,r = 1;
while(l<=r){
int cnt = 0;
for(register int i=l;i<=r;++i){
int u = queue[i];
for(register int j=head2[u];j;j=g[j].next){
int v = g[j].v;
Node[v].count++;
if(Node[v].vis==1)continue;
cnt++;
Node[v].vis=1;
queue[r+cnt]=v;
}
}
l=r+1;r+=cnt;
}
}
inline void check(){
for(register int i=1;i<=N;++i){
if(Node[i].count!=Node[i].size)Node[i].vis=0;
}
}
int main(){
N=read();M=read();
for(register int i=1;i<=N;++i){
head1[i]=0;head2[i]=0;Node[i].count=0;
Node[i].size=0;Node[i].vis=0;
}
for(register int i=1;i<=M;++i){
G[i].next=0;g[i].next=0;
}
int u,v;
for(register int i=1;i<=M;++i){
u=read();v=read();add(u,v);
Node[u].size++;
}
s = read();t = read();
BFS1();
if(Node[s].vis==0){
puts("-1");
return 0;
}
check();
if(Node[s].vis==0){
puts("-1");
return 0;
}
int l=1,r=1;
queue[1]=s;
Node[s].vis=2;
int ans = 0;
while(l<=r){
ans++;
int cnt = 0;
for(register int i=l;i<=r;++i){
int u = queue[i];
for(register int j=head1[u];j;j=G[j].next){
int v = G[j].v;
if(Node[v].vis==0||Node[v].vis==2)continue;
if(v==t){
printf("%d",ans);
return 0;
}
cnt++;
queue[cnt+r]=v;
Node[v].vis=2;
}
}
l=r+1;r+=cnt;
}
puts("-1");
return 0;
}
score:100
T3
Solution
高精度,具体做法想不出来,写了个30分的暴力交上去。
#include<cstdio>
using namespace std;
long long a[105];
int answer[1000005];
int N,M;
inline bool C(int x){
long long sum = 0;
long long mul = 1;
for(register int i=0;i<=N;++i){
sum += mul*a[i];
mul*=x;
}
if(sum==0)return true;
else return false;
}
int main(){
scanf("%d%d",&N,&M);
for(register int i=0;i<=N;++i)scanf("%lld",&a[i]);
int ans = 0;
for(register int i=1;i<=M;++i){
if(C(i)){
ans+=1;
answer[ans]=i;
}
}
printf("%d\n",ans);
for(register int i=1;i<=ans;++i)printf("%d\n",answer[i]);
return 0;
}
score:30
DAY2总分:230
总分:450
总结
肯定
自己写暴力越来越熟练了!!~
否定
对于难题没有更好的办法,仍需努力!
2018.2.25(开学)