zoukankan      html  css  js  c++  java
  • [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);
    } 
    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<<"
    ";
    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<<"
    "<<ans; 
    66     }
    67     
    68 
    69 //    cout<<"
    
    
    ";
    70 //    for(int i=0;i<=n;i++) cout<<has[i]<<"
    ";
    71 //    for(int i=0;i<=n;i++)
    72 //        for(int j=l[i]+1;j<h[i];j++){
    73 //            printf("%d %d %d
    ",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
    ",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<<"
    ";
    52     for(int i=1;i<=m;i++) {
    53         if(vis[i]==0) printf("%d
    ",i);
    54     }    
    55 } 
    View Code

    总结

    做的水分太多了。。。。。。。。真实比赛恐怕一半的分数都很难吧。没办法在弱校比赛经验不足也没学长领着,只能自己摸索。想到前几个月去青岛比赛的经历就不堪回首(我的成语没用错吧,语文一直弱),一道题调的不太好结果心烦意乱后面基本胡乱打了,唉;

    我做的题太少了,打代码也太慢,并且比赛策略几乎为0,就瞎看些理论知识,有什么用!争取在今年noip前让自己变强吧(学校太弱,平常只有周五晚自习可以去机房;我学习也太好,(其他人)不舍得停课,甚至连比赛前可能也不一定,唉~~o(>_<)o ~~)。

  • 相关阅读:
    开源交易所源码
    ThinkCMF框架上的任意内容包含漏洞
    UAC绕过初探
    WinDbg常用命令系列---显示当前异常处理程序链!exchain
    WinDbg常用命令系列---错误消息显示!error
    WinDbg常用命令系列---检查符号X
    WinDbg常用命令系列---线程栈中局部上下文切换.frame
    WinDbg常用命令系列---显示数字格式化.formats
    WinDbg常用命令系列---清屏
    WinDbg常用命令系列---!address
  • 原文地址:https://www.cnblogs.com/candy99/p/5721724.html
Copyright © 2011-2022 走看看