[NOIP2014]自測

Candy?發表於2016-07-30

這兩天做完了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);
} 
View Code

【聯合權值】

暴力:列舉點對中間那個店。(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 }
View Code

正解:看了課件才想到

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 }
View Code

 

【飛揚的小鳥】

我只會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 }
View Code

 

【無線網路發射器選址】

好水..................

資料範圍這麼小,我實在捨不得就用它練了練二維字首和,結果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 }
View Code

 

【尋找道路】

以前看過題解了,所以做法一下子回憶過來了

倒著搜一遍與終點連通的點

很像白書上那一道理想路徑(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 }
View Code

 

【解方程】

坑人的一道。。。。。

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 } 
View Code

 

 

總結

做的水分太多了。。。。。。。。真實比賽恐怕一半的分數都很難吧。沒辦法在弱校比賽經驗不足也沒學長領著,只能自己摸索。想到前幾個月去青島比賽的經歷就不堪回首(我的成語沒用錯吧,語文一直弱),一道題調的不太好結果心煩意亂後面基本胡亂打了,唉;

我做的題太少了,打程式碼也太慢,並且比賽策略幾乎為0,就瞎看些理論知識,有什麼用!爭取在今年noip前讓自己變強吧(學校太弱,平常只有週五晚自習可以去機房;我學習也太好,(其他人)不捨得停課,甚至連比賽前可能也不一定,唉~~o(>_<)o ~~)。

 

相關文章