[NOIP2014]自测
这两天做完了2014年的noip提高。
因为以前看了SDSC2016时gty的课件,题目思路都知道了一点,做起来没多大困难。
100+100+75+100+100+70=545
里面水分好多,好多题都是提交几次WA后才过,并且基本没打对拍........
今年noip我要考这么高的分该多好!!!(然而别做梦了,一比赛就慌,打代码又慢ヾ(=゚・゚=)ノ喵♪)
【生活大爆炸版石头剪刀布】
太水了..........
注意看清那个图
#include<iostream>
#include<cstdio>
using namespace std;
const int N=205;
int n,na,nb;
int a[N],b[N],jud[5][5];
int ga=0,gb=0;
void set(int i,int j){ //i win j
jud[i][j]=1;
jud[j][i]=0;
}
void init(){
for(int i=0;i<5;i++) jud[i][i]=2;
set(1,0);
set(0,2);
set(0,3);
set(4,0);
set(2,1);
set(1,3);
set(4,1);
set(3,2);
set(2,4);
set(3,4);
}
int main(){
cin>>n>>na>>nb;
for(int i=0;i<na;i++)
cin>>a[i];
for(int i=0;i<nb;i++)
cin>>b[i];
init();
for(int i=0;i<n;i++){
int tmp=jud[a[i%na]][b[i%nb]];
if(tmp==1) ga++;
else if(tmp==0) gb++;
}
printf("%d %d",ga,gb);
}
【联合权值】
暴力:枚举点对中间那个店。(O(n^2) 菊花图)
1 //baoli
2 #include<iostream>
3 #include<cstdio>
4 #include<vector>
5 using namespace std;
6 typedef long long ll;
7 const int N=200005,MOD=10007;
8
9 int n;
10
11 struct node{
12 ll w;
13 vector<int> ch;
14 } g[N];
15 int cnt=0;
16 void add(int u,int v){
17 g[u].ch.push_back(v);
18 g[v].ch.push_back(u);
19 }
20
21 ll mx=-10000,ans=0;
22 void sol(int u){
23 ll p=0;
24 int sn=g[u].ch.size();
25 for(int i=0;i<sn;i++)
26 for(int j=0;j<sn;j++){
27 if(i==j) continue;
28 int ch1=g[u].ch[i],ch2=g[u].ch[j];
29 mx=max(mx,p=g[ch1].w*g[ch2].w);
30 ans+=p%MOD;
31 }
32 }
33 int main(){
34 //freopen("link.in","r",stdin);
35 //freopen("link.out","w",stdout);
36
37 scanf("%d",&n);
38 int u,v,w;
39 for(int i=1;i<=n-1;i++){
40 scanf("%d%d",&u,&v);
41 add(u,v);
42 }
43 for(int i=1;i<=n;i++){
44 scanf("%d",&w);
45 g[i].w=w;
46 }
47
48 for(int i=1;i<=n;i++) sol(i);
49
50 cout<<mx<<" "<<ans%MOD;
51 //fclose(stdin);
52 //fclose(stdout);
53 return 0;
54 }
正解:看了课件才想到
max:找相邻节点中权值最大的两个
sum:加法结合律....预处理相邻节点的和,[a*(sum-a)+b*(sum-b)+…]
注意(u,v)和(v,u)都要算
图的话,用vector就行了
1 #include<iostream>
2 #include<cstdio>
3 #include<vector>
4 using namespace std;
5 typedef long long ll;
6 const int N=200005,MOD=10007;
7
8 int n;
9
10 vector<int> e[N];
11 ll w[N];
12 ll sum[N];
13
14 ll mx=-10000,ans=0;
15 void sol(int u){
16 int sn=e[u].size();
17 int mx1=-1,mx2=-1;
18 for(int i=0;i<sn;i++){
19 if(mx1==-1 || w[e[u][i]]>w[e[u][mx1]]) mx1=i;
20 sum[u]=(sum[u]+w[e[u][i]])%MOD;
21 }
22 for(int i=0;i<sn;i++){
23 if(i==mx1) continue;
24 if(mx2==-1 || w[e[u][i]]>w[e[u][mx2]]) mx2=i;
25 }
26 if(mx1!=-1 && mx2!=-1)
27 mx=max(mx,w[e[u][mx1]]*w[e[u][mx2]]);
28
29 ll tmp=0;
30 for(int i=0;i<sn;i++){
31 tmp=(tmp+w[e[u][i]]*(sum[u]-w[e[u][i]]+MOD)%MOD)%MOD;
32 }
33 ans=(ans+tmp)%MOD;
34 }
35 int main(){
36 //freopen("link.in","r",stdin);
37 //freopen("link.out","w",stdout);
38 int u,v,ww;
39 scanf("%d",&n);
40 for(int i=1;i<=n-1;i++){
41 scanf("%d%d",&u,&v);
42 e[u].push_back(v);
43 e[v].push_back(u);
44 }
45 for(int i=1;i<=n;i++){
46 scanf("%d",&ww);
47 w[i]=ww;
48 }
49
50 for(int i=1;i<=n;i++) sol(i);
51 cout<<mx<<" "<<ans%MOD;
52 //fclose(stdin);
53 //fclose(stdout);
54 return 0;
55 }
【飞扬的小鸟】
我只会70%的状态转移方程,不知为什么多拿了5分ヾ(・ω・`。)
f(i,j)--->到i,j位置的最少点击数
f(i,j)=min{f(i-1,j+Yi-1), f(i-1,j-Xi-1 *k)+k | Li-1<j-Xi-1 *k,j+Yi-1 <Hi-1}
特判j==m 从i-1的任何地方都可以
[tips]:预设Li=0,Hi=m+1,省好多麻烦
注意碰到地和管道就算死,他问你通过几个管道
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 const int N=10005,M=1005,INF=1e9;
6 int n,m,k, x,y,p,ll,hh;
7 int up[N],down[N],l[N],h[N], has[N];
8 int f[N][M];
9 int ans=INF;
10 void dp(){
11 for(int i=1;i<=n;i++)
12 for(int j=1;j<=m;j++)
13 f[i][j]=INF;
14
15 for(int i=1;i<=n;i++)
16 for(int j=l[i]+1;j<h[i];j++){
17 int &now=f[i][j];
18 if(j==m)
19 for(int z=h[i-1]-1;z>l[i-1];z--){
20 if(z==m) now=min(now,f[i-1][z]+1);
21 else if((m-z)%up[i-1]==0) now=min(now,f[i-1][z]+(m-z)/up[i-1]);
22 else now=min(now,f[i-1][z]+(m-z)/up[i-1]+1);
23 }
24 else{
25 if(j+down[i-1]<h[i-1]) now=min(now,f[i-1][j+down[i-1]]);
26 for(int k=1;;k++){
27 if(j-up[i-1]*k>l[i-1]) now=min(now,f[i-1][j-up[i-1]*k]+k);
28 else break;
29 }
30 }
31 }
32 }
33 int main(){
34 scanf("%d%d%d",&n,&m,&k);
35 for(int i=0;i<=n;i++) h[i]=m+1;
36 for(int i=0;i<n;i++){
37 scanf("%d%d",&x,&y);
38 up[i]=x;
39 down[i]=y;
40 }
41 for(int i=0;i<k;i++){
42 scanf("%d%d%d",&p,&ll,&hh);
43 l[p]=ll;
44 h[p]=hh;
45 has[p]=1;
46 }
47
48 dp();
49 for(int j=l[n]+1;j<h[n];j++) ans=min(ans,f[n][j]);
50 if(ans==INF){
51 cout<<0<<"\n";
52 int flag=0;
53 for(int i=n-1;i>=0;i--){
54 for(int j=l[i]+1;j<h[i];j++){
55 if(f[i][j]<INF) {
56 int tmp=0;
57 for(int z=0;z<=i;z++) tmp+=has[z];
58 cout<<tmp;
59 flag=1;break;
60 }
61 }
62 if(flag) break;
63 }
64 }else{
65 cout<<1<<"\n"<<ans;
66 }
67
68
69 // cout<<"\n\n\n";
70 // for(int i=0;i<=n;i++) cout<<has[i]<<"\n";
71 // for(int i=0;i<=n;i++)
72 // for(int j=l[i]+1;j<h[i];j++){
73 // printf("%d %d %d\n",i,j,f[i][j]);
74 // }
75
76 }
【无线网络发射器选址】
好水..................
数据范围这么小,我实在舍不得就用它练了练二维前缀和,结果WA好几次才过
注意方案数不能只从(x+d,y+d)枚举,可能丢解
以后别从0开始了做死
1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 using namespace std;
5 const int N=129;
6 int d,n;
7 int g[N][N],s[N][N];
8 int x,y,k;
9
10 void sss(){
11 s[0][0]=g[0][0];
12 for(int i=1;i<N;i++) s[0][i]=s[0][i-1]+g[0][i],
13 s[i][0]=s[i-1][0]+g[i][0];
14 for(int i=1;i<N;i++)
15 for(int j=1;j<N;j++)
16 s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+g[i][j];
17 }
18
19 inline int sre(int x,int y){
20 if(x<0 ||y<0) return 0;
21 x= x>=N ? N-1 :x;
22 y= y>=N ? N-1 :y;
23 return s[x][y];
24 }
25 inline int get(int x1,int y1,int x2,int y2){
26 return sre(x2,y2)-sre(x2,y1-1)-sre(x1-1,y2)+sre(x1-1,y1-1);
27 }
28
29 int cnt=0,mx=-1;
30 int main(){
31 scanf("%d%d",&d,&n);
32 for(int i=0;i<n;i++){
33 scanf("%d%d%d",&x,&y,&k);
34 g[x][y]=k;
35 }
36
37 sss();
38
39 for(int x=d;x+d<N;x++)
40 for(int y=d;y+d<N;y++)
41 mx=max(mx,get(x-d,y-d,x+d,y+d));
42
43 for(int x=0;x<N;x++)
44 for(int y=0;y<N;y++)
45 if(get(x-d,y-d,x+d,y+d)==mx) cnt++;//printf("%d %d\n",x,y),cnt++;
46
47 cout<<cnt<<" "<<mx;
48 }
【寻找道路】
以前看过题解了,所以做法一下子回忆过来了
倒着搜一遍与终点连通的点
很像白书上那一道理想路径(Ideal Path),虽然我还没做那道题
注意是路径上所有点所指向的点
邻接表比较合适吧,我还见了一个反向图,用的f来区别,结果好乱●﹏●
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<queue>
5 using namespace std;
6 const int N=10005,M=200005;
7
8 struct edge{
9 int v,ne;
10 }e[M];
11 int n,m,x,y,s,t;
12 int h[N];
13 int cnt=0;
14 void ins(int u,int v){
15 e[++cnt].v=v;
16 e[cnt].ne=h[u];
17 h[u]=cnt;
18 }
19
20 edge ef[M];
21 int hf[N];
22 int cntf=0;
23 void insf(int u,int v){
24 ef[++cntf].v=v;
25 ef[cntf].ne=hf[u];
26 hf[u]=cntf;
27 }
28
29 bool vis[N],del[N];
30 void dfsf(int u){
31 vis[u]=true;
32 for(int i=hf[u];i;i=ef[i].ne){
33 int v=ef[i].v;
34 if(!vis[v])
35 dfsf(v);
36 }
37 }
38
39 int d[N];
40 void bfs(int s){
41 memset(vis,0,sizeof(vis));
42 memset(d,-1,sizeof(d));
43 queue<int> q;
44 q.push(s);
45 d[s]=0;
46 while(!q.empty()){
47 int u=q.front();q.pop();
48 for(int i=h[u];i;i=e[i].ne){
49 int v=e[i].v;
50 if(del[v]||vis[v]) continue;
51 q.push(v);
52 vis[v]=1;
53 d[v]=d[u]+1;
54 if(v==t) break;
55 }
56 }
57 }
58 int main(){
59 scanf("%d%d",&n,&m);
60 for(int i=1;i<=m;i++){
61 scanf("%d%d",&x,&y);
62 ins(x,y);
63 insf(y,x);
64 }
65 scanf("%d%d",&s,&t);
66
67 dfsf(t);
68 for(int u=1;u<=n;u++)
69 if(!vis[u]){
70 del[N]=true;
71 for(int i=hf[u];i;i=ef[i].ne){
72 int v=ef[i].v;
73 del[v]=true;
74 }
75 }
76
77 bfs(s);
78
79 cout<<d[t];
80 }
【解方程】
坑人的一道。。。。。
30%小学生暴力
50%都说是高精,我也这么说了ヾ(゚∀゚ゞ)
70%................看了课件 %质数 啊 %%%
100%..............又看了课件 “如果我们模的数字是k。左边式子带入x和带入x+k是没有区别的。如果我们把质数k取得小一些,这样x就不用试1~m,而是试1~k。这样复杂度就变成 O(nkprime),如果k取10^4左右就完全没有问题。”
试着做了下70%的,随手写了个欧拉筛法选几个素数(→_→),又写了个大整数取模和快速幂取模,结果WA了,目测快速幂取模写抽了(→_→)*2......闷闷不乐一会看看了黄学长的blog,咦好像可以预处理pre[m][j]--->m^j%prime,然后就爆内存了(→_→)*3。发现黄学长没用long long我也改int,然后把M改成70%M的规模,就拿了70分...ヘ(_ _ヘ)
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 const int N=105,L=10005,M=10005;
6
7 int n,m;
8 char a[N][L];
9 int aint[N];
10 int mod[5]={11261,19997,22877,21893,14843};
11
12 void getmod(char *a,int len,int x,int p){
13 int tmp=0,flag=0;
14 if(a[0]=='-') flag=1;
15 else tmp=a[0]-'0';
16
17 for(int j=1;j<len;j++)
18 tmp=(tmp*10+a[j]-'0')%p;
19 aint[x]=flag?-tmp:tmp;
20 }
21
22 //long long powmod(long long a,int b,long long p){
23 // long long ans=1;
24 // for(;b;b>>=1,a=(a*a)%p)
25 // if(b&1) ans=(ans*a)%p;
26 // return ans;
27 //}
28 int pre[M][N];
29 bool vis[M];
30 int main(){
31 scanf("%d%d",&n,&m);
32 for(int i=0;i<=n;i++)
33 scanf("%s",a[i]);
34
35 for(int i=0;i<5;i++){
36 for(int x=0;x<=n;x++) getmod(a[x],strlen(a[x]),x,mod[i]);
37
38 for(int j=1;j<=m;j++) pre[j][0]=1;
39 for(int j=1;j<=m;j++)
40 for(int z=1;z<=n;z++) pre[j][z]=(pre[j][z-1]*j)%mod[i];
41
42 for(int j=1;j<=m;j++){
43 long long ans=aint[0];
44 for(int z=1;z<=n;z++)
45 ans=(ans+aint[z]*pre[j][z])%mod[i];
46 if(ans!=0) vis[j]=1;
47 }
48 }
49 int num=0;
50 for(int i=1;i<=m;i++) if(vis[i]==0) num++;
51 cout<<num<<"\n";
52 for(int i=1;i<=m;i++) {
53 if(vis[i]==0) printf("%d\n",i);
54 }
55 }
总结
做的水分太多了。。。。。。。。真实比赛恐怕一半的分数都很难吧。没办法在弱校比赛经验不足也没学长领着,只能自己摸索。想到前几个月去青岛比赛的经历就不堪回首(我的成语没用错吧,语文一直弱),一道题调的不太好结果心烦意乱后面基本胡乱打了,唉;
我做的题太少了,打代码也太慢,并且比赛策略几乎为0,就瞎看些理论知识,有什么用!争取在今年noip前让自己变强吧(学校太弱,平常只有周五晚自习可以去机房;我学习也太好,(其他人)不舍得停课,甚至连比赛前可能也不一定,唉~~o(>_<)o ~~)。