2010 辽宁省省赛 题解

来源:互联网 发布:曹县大集淘宝村现状 编辑:程序博客网 时间:2024/05/01 12:01

题目来源:2010辽宁省省赛


比赛名:NBUT 2012 Weekly - 13th Oct for 11x


题目链接:http://ac.nbutoj.com/Problem.xhtml?page=3   1217~1225


比赛的时候过了8题,H题后来知道是什么了。。但是还是不知道怎么求。。。


A题:水题,字符串比较。

#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;main(){     int n;     while(scanf("%d",&n)!=EOF)     {         bool flag=1;         for(int i=0;i<n;i++)         {            string c;            cin>>c;            if(c=="bowl"||c=="knife"||c=="fork"||c=="chopsticks")            {               if(flag==0)               printf(" ");               cout<<c;               flag=0;            }         }         puts("");     }     return 0;}


B题:给一棵树,问树上两个点,哪个的深度小。

           直接每次把两个点移动到父节点,记录下他们走过的点,某个点走到另一个点走过的点,说明这个点深度大。

#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;int fa[2022]={0};int vis1[2022]={0};int vis2[2022]={0};main(){     int n;     while(scanf("%d",&n)!=EOF)     {         clr(fa);         clr(vis1);         clr(vis2);        // clrset(fa,2000);         for(int i=0;i<n;i++)         {             int a,b;             scanf("%d%d",&a,&b);             fa[a]=b;         }         vis1[1]=1;         vis2[2]=1;         int p1=1,p2=2;         while(1)         {             int x2=fa[p1];             int y2=fa[p2];             if(x2==y2)             {                  puts("You are my brother");                  break;             }             else if(vis1[y2]==1)             {                 puts("You are my younger");                 break;             }             else if(vis2[x2]==1)             {                 puts("You are my elder");                 break;             }             else             {                 vis1[x2]=1;                 vis2[y2]=1;                 p1=x2;                 p2=y2;             }         }     //    return 0;     }     return 0;}




C题:给4个1位数字,用计算器的格式输出。

#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;char cc[3][31]={"    _  _     _  _  _  _  _  _ ","  | _| _||_||_ |_   ||_||_|| |","  ||_  _|  | _||_|  ||_| _||_|"};main(){    int a,b,c,d;    while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF)    {        for(int i=0;i<3;i++)        {            for(int j=0;j<3;j++)            {               printf("%c",cc[i][(((a-1)+10)%10)*3+j]);            }            for(int j=0;j<3;j++)            {               printf("%c",cc[i][(((b-1)+10)%10)*3+j]);            }            for(int j=0;j<3;j++)            {               printf("%c",cc[i][(((c-1)+10)%10)*3+j]);            }            for(int j=0;j<3;j++)            {               printf("%c",cc[i][(((d-1)+10)%10)*3+j]);            }            puts("");        }
 } return 0;
D:给三个字符串列表,第一个代表要来A国的人,第二个代表B国的间谍,第三个代表A国派去B国的间谍【也就是A国的人】,问来的人中,B国的间谍有哪些  

#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;map<string,int>mp;int main(){     int n1,n2,n3;     while(scanf("%d%d%d",&n1,&n2,&n3)!=EOF)     {         string c[10000];         mp.clear();         for(int i=0;i<n1;i++)         {             string c1;             cin>>c1;             mp[c1]=1;         }         for(int i=0;i<n2;i++)         {             cin>>c[i];             mp[c[i]]++;         }         for(int i=0;i<n3;i++)         {             string c1;             cin>>c1;             mp[c1]--;         }         bool flag=0;         for(int i=0;i<n2;i++)           if(mp[c[i]]==2)           {              if(flag)                printf(" ");              cout<<c[i];              flag=1;           }         if(flag==0)         {            puts("No enemy spy");         }         else puts("");     }     return 0;}
E题:给一个图,图上的每条边都被一个人管理着,每条边有个过路费,第一次经过a管理的路时,只用交过路费,第二次要多交e[a],第三次要多交f[a]。问0~n-1的最少花费的路径。

          正解应该是状态压缩搜索吧。因为管理者最多有9个,所以我们可以用一个3^9的数代表被管理的道路的状态。dp[i][j]代表到第i个点,状态为j,最少花费为多少,直接记忆化搜索一发应该就行了。。

          比赛的时候直接爆搜过了,当时没多想就觉得数据很小有可能爆过去。。


#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;struct node{     int val;     int emp;     int to;};vector<node>road[111];int e[11]={0};int f[11]={0};int use[11]={0};int vis[111]={0};int n,m,q;long long minn=INF;void find(int pos,int sum){     if(sum>=minn)        return;     if(pos==n-1)     {         minn=sum;         return;     }     for(int i=0;i<road[pos].size();i++)     {        int next=road[pos][i].to;        if(!vis[next])        {             vis[next]=1;             int k=road[pos][i].emp;             int c=road[pos][i].val;             use[k]++;             if(use[k]==1)                 find(next,sum+c);             else if(use[k]==2)                 find(next,sum+c+e[k]);             else find(next,sum+c+f[k]);             vis[next]=0;             use[k]--;        }     }}main(){     while(scanf("%d%d%d",&n,&m,&q)!=EOF)     {         clr(vis);         clr(use);         for(int i=0;i<=100;i++)            road[i].clear();         for(int i=0;i<m;i++)            scanf("%d",e+i);         for(int i=0;i<m;i++)            scanf("%d",f+i);         for(int i=0;i<q;i++)         {             int a,b,c,d;             scanf("%d%d%d%d",&a,&b,&c,&d);             node temp;             temp.to=b;             temp.val=d;             temp.emp=c;             road[a].push_back(temp);         }         minn=INF;         find(0,0);         if(minn==INF)            puts("-1");         else printf("%d\n",minn);     }     return 0;}//爆搜的。。状压的看我心情写不写了。。。
F题:给一个字符串,和n个子串,每个子串有一个权值,用子串去填充原串,一个串可以用多次,问填充后最大权值是多少,若不能完全填充输出-1 首先肯定是要DP的,但是因为原串长10000,子串长30,并且有1000个,所以复杂度会有3亿不科学。于是想到用字典树。 将所有串加到字典树中,然后memset(dp,-1,sizeof(dp));,dp[0]=0,之后直接dp,对于每个不为-1的dp值,去查找这个点往后的30个子串是否存在于字典树中,若存在则更新下一个dp值。然后这样会T,有一个优化必须加,往后找子串的时候,假如找到某一个子串,在查找过程中遇到了-1而退出,说明后面的子串肯定都不满足条件,就可以直接退出本次DP。加了之后170ms过。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;struct node{     int end;     int val;     int next[26];}trie[50000];int top=1;inline void init(){     trie[0].end=0;     trie[0].val=0;     for(int i=0;i<26;i++)        trie[0].next[i]=-1;     top=1;}inline void insert(char *c,int pos,int v){    if(c[0]==0)    {        trie[pos].end=1;        trie[pos].val=v;        return;    }    else if(trie[pos].next[c[0]-'a']!=-1)    {        insert(c+1,trie[pos].next[c[0]-'a'],v);    }    else    {        trie[top].end=0;        trie[top].val=0;        for(int i=0;i<26;i++)           trie[top].next[i]=-1;        trie[pos].next[c[0]-'a']=top++;        insert(c+1,top-1,v);    }}inline int find(char *c,int pos){    if(c[0]==0)    {        if(trie[pos].end)           return trie[pos].val;        return -1;    }    else if(trie[pos].next[c[0]-'a']==-1)       return -2;    else    {       return find(c+1,trie[pos].next[c[0]-'a']);    }}main(){     int n;     while(scanf("%d",&n)!=EOF)     {         char need[10011]={0};         need[0]='#';         scanf("%s",need+1);         int len=strlen(need);         int dp[10011];         memset(dp,-1,sizeof(dp));         dp[0]=0;         init();         for(int i=0;i<n;i++)         {             char c[100]={0};             scanf("%s",c);             int d;             scanf("%d",&d);             insert(c,0,d);         }         for(int i=0;i<len-1;i++)         {             if(dp[i]==-1)                continue;             char c[100]={0};             for(int j=0;j<30,i+j+1<len;j++)             {                c[j]=need[i+j+1];                int x=find(c,0);                if(x>=0)                {                   if(dp[i+j+1]<dp[i]+x)                   dp[i+j+1]=dp[i]+x;                }                else if(x==-2)                   break;             }         }         if(dp[len-1]!=-1)           printf("%d\n",dp[len-1]);         else printf("-1\n");     }     return 0;}

G题:问a,b中的亲和数对数

           直接打表= =。。。

#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;int aa[1000]={284,1210,2924,5564,6368,10856,14595,18416,76084,66992,71145,87633,88730,124155,139815,123152,153176,168730,176336,180848,203432,202444,365084,389924,430402,399592,455344,486178,514736,525915,669688,686072,691256,712216,652664,783556,796696,863835,901424,980984,1125765,1043096,1099390,1189150,1292570,1438983,1286744,1340235,1483850,1486845,1464592,1747930,1749212,1598470,2062570,1870245,2090656,2429030,2941672,2874064,3077354,2928136,2947216,3716164,3721544,3892670,4300136,4006736,4314616,4488910,4445050};int bb[1000]={220,1184,2620,5020,6232,10744,12285,17296,63020,66928,67095,69615,79750,100485,122265,122368,141664,142310,171856,176272,185368,196724,280540,308620,319550,356408,437456,469028,503056,522405,600392,609928,624184,635624,643336,667964,726104,802725,879712,898216,947835,998104,1077890,1154450,1156870,1175265,1185376,1280565,1328470,1358595,1392368,1466150,1468324,1511930,1669910,1798875,2082464,2236570,2652728,2723792,2728726,2739704,2802416,2803580,3276856,3606850,3786904,3805264,4238984,4246130,4259750};main(){     int a,b;     while(scanf("%d%d",&a,&b)!=EOF)     {         int cnt=0;         for(int i=0;i<71;i++)         {            if(bb[i]>=a&&aa[i]<=b)               cnt++;       //     else if(aa[i]>b)       //        break;         }         printf("%d\n",cnt);     }     return 0;}

H题:解佩尔方程。。。

           当时就跪了。。想了很久都不会,结果熊教一眼就看出是佩尔方程Orz。。但是还是不会求。。。提供一份代码,以后研究去。。

code by eapink

#include<cstdio>#include<cmath>#include<cstdio>#include<iostream>#include<sstream>#include<vector>using namespace std;int count(string s){    int count=0;    for(int i=0;i<s.length();i++)        if(s[i]=='0') count++;        else break;    return count;}  string muling(string s1,string s2){    string cheng(s1.length()+s2.length(),'0');    for(int n2=s2.length()-1;n2>=0;n2--)        if(s2[n2])            for(int n1=s1.length()-1,n=n2+s1.length();n1>=0;--n1,--n)            {                int temp=(s1[n1]-'0')*(s2[n2]-'0');                cheng[n-1]=char(cheng[n-1]+(cheng[n]+temp-'0')/10);                cheng[n]=char((cheng[n]+temp-'0')%10+'0');            }            if(count(cheng)==cheng.length())                return "0";            return cheng.substr(cheng.find_first_not_of('0'));}  string sum(string s1,string s2){    if(s1.length()<s2.length())    {        string temp=s1;        s1=s2;        s2=temp;    }    for(int n1=s1.length()-1,n2=s2.length()-1;n1>=0;n1--,n2--)    {        s1[n1]=char(s1[n1]+(n2>=0?s2[n2]-'0':0));        if(s1[n1]-'0'>=10)        {            s1[n1]=char((s1[n1]-'0')%10+'0');            if(n1) s1[n1-1]++;            else s1="1"+s1;        }    }    return s1;}    string change(int a){    string s1="";    char s2[10000];    int i=0;    while(a)    {        s2[i++]=(a%10)+'0';        a/=10;    }    for(--i;i>=0;--i)        s1+=s2[i];    return s1;}  int main(){    //freopen("b.txt","w",stdout);    string h[3],k[3],aa;    long long lp[3],lq[3],a[3];    int n;    while(scanf("%d",&n)!=EOF)    {        if((int)sqrt((double)n)*(int)sqrt((double)n)==n)        {            printf("no solution\n");            continue;        }        int s;        a[2]=s=sqrt((double)n);        h[0]="0";h[1]="1";        k[0]="1";k[1]="0";        lp[1]=0;lq[1]=1;        int p=2;        while(1)        {            if(p==0)            {                lp[0]=-lp[2]+a[0]*lq[2];                lq[0]=(n-lp[0]*lp[0])/lq[2];                a[1]=floor((double)(lp[0]+s)/lq[0]);                h[0]=sum(muling(change(a[0]),h[2]),h[1]);                k[0]=sum(muling(change(a[0]),k[2]),k[1]);                              }            else if(p==1)            {                lp[1]=-lp[0]+a[1]*lq[0];                lq[1]=(n-lp[1]*lp[1])/lq[0];                a[2]=floor((double)(lp[1]+s)/lq[1]);                h[1]=sum(muling(change(a[1]),h[0]),h[2]);                k[1]=sum(muling(change(a[1]),k[0]),k[2]);            }            else            {                lp[2]=-lp[1]+a[2]*lq[1];                lq[2]=(n-lp[2]*lp[2])/lq[1];                a[0]=floor((double)(lp[2]+s)/lq[2]);                h[2]=sum(muling(change(a[2]),h[1]),h[0]);                k[2]=sum(muling(change(a[2]),k[1]),k[0]);            }            string s1=muling(h[p],h[p]);            string s2=sum("1",muling(change(n),muling(k[p],k[p])));            if(s1==s2) //h[p]*h[p]==1+n*k[p]*k[p]            {                cout<<h[p]<<endl;                break;            }            p++;            p%=3;        }    }    return 0;}

I题:1~n n个数排成一行,每次把偶数位置上的数抽出来,再把奇数位置上的一个一个接在后面,形成一个新数列,问M次操作之后,前X个数分别是什么。

       因为M很大,肯定不能暴力。

       先假设这个数列无限大,那么M次操作之后,第一个数是2^m,第二个数是2*2^m,第三个数是3*2^m……………………

       那么假如这个数列的个数是奇数的话,因为2^m和n互质,把每个数%n就能得到答案了。

       那么如果这个数是偶数呢?很容易发现,如果数列是奇数的话,最后一个数永远都不会变,那么我们能把它看成一个n+1长度的数列,对n+1取模就行了。

      加个快速幂,然后如果模出0的话记得变成n。

#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x)  memset(x,0,sizeof(x));#define clrto(x,siz,y)  for(int xx=0;xx<=siz;xx++)  x[xx]=y;#define clrset(x,siz)  for(int xx=0;xx<=siz;xx++)  x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++)  x[xx].clear();#define fop   freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y)  for(int xx=0;xx<siz;xx++)  x[xx]=y[xx];using namespace std;main(){    int n,m,x;    while(scanf("%d%d%d",&n,&m,&x)!=EOF)    {        if(n%2==0)           n++;        long long a=1;        long long temp=2;        while(m)        {            if(m&1)               a*=temp,a%=n;            temp*=temp,temp%=n;            m>>=1;        }        int sum=0;        for(int i=0;i<x;i++)        {           sum+=a;           sum%=n;           printf("%d%c",sum==0?n:sum,i==x-1?'\n':' ');        }    }    return 0;}



终于完整的做完一次比赛了。。。

虽然貌似略水。。


          Posted by 135678942570   blog.csdn.net/ttl_135678942570