2010 辽宁省省赛 题解

题目来源: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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值