山东省第四届ACM大学生程序设计竞赛解题报告(部分)

2013年"浪潮杯"山东省第四届ACM大学生程序设计竞赛排名:http://acm.upc.edu.cn/ranklist/

一、第J题坑爹大水题,模拟一下就行了

J:Contest Print Server
【题解】:
  题目大意:输入 n,s,x,y,mod  分别队伍数n,还有一个s生成函数 s=((s*x)+y)%mod,就是打印机根据要求打印纸张,打印到s时,打印机将重置,生成新的s
【code】:
  
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string.h>
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     int t;
 9     scanf("%d",&t);
10     while(t--)
11     {
12         int n,s,x,y,mod,i,p;
13         char team[30],str[20];
14         int cnt = 0;
15         scanf("%d%d%d%d%d",&n,&s,&x,&y,&mod);
16         for(i=0;i<n;i++)
17         {
18             scanf("%s%s%d%s",team,str,&p,str);
19             while(1)
20             {
21                 if(p<=s-cnt)
22                 {
23                     cnt+=p;
24                     printf("%d pages for %s\n",p,team);
25                     break;
26                 }
27                 else
28                 {
29                     printf("%d pages for %s\n",s-cnt,team);
30                     s = ((s*x)+y)%mod;
31                     cnt = 0;
32                 }
33             }
34         }
35         putchar(10);
36     }
37     return 0;
38 }
View Code

二、第I题概率DP问题

I:The number of steps
【题解】:
      1
     /  \
   2 —  3
  /  \  /  \
4 — 5 — 6
输入概率:a b c d e 分别表示:
  例如:
     1
    a/ \b    只有左右孩子的就是概率a、b 
     
              c — 3 
                 d / \e    有左右孩子并且有左兄弟  概率分别为 c、d、e
 
     — 5  如果只有左兄弟的话概率为 1
  
  只有以上这三种情况:
    如果f(i)表示第i步达到目的地的概率的话
    结果ans = f(1)*1 + f(2)*2 + f(3)*3 + ....+f(n)*n
【code】:
 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 double dp[100][50][50];
 7 int main()
 8 {
 9     int n;
10     while(~scanf("%d",&n)&&n)
11     {
12         double a,b,c,d,e;
13         scanf("%lf%lf%lf%lf%lf",&a,&b,&c,&d,&e);
14         memset(dp,0,sizeof(dp));
15         dp[0][1][1] = 1;
16         int i,j,k;
17         for(k=1;k<=(n-1)*2;k++)
18         {
19             for(i=1;i<=n;i++)
20             {
21                 for(j=1;j<=i;j++)
22                 {
23                     if(j-1<1&&i+1<=n&&j+1<=n)
24                     {
25                         dp[k][i+1][j] += dp[k-1][i][j]*a;
26                         dp[k][i+1][j+1] += dp[k-1][i][j]*b;
27                     }
28                     else if(j-1>=1&&i+1<=n&&j+1<=n)
29                     {
30                         dp[k][i][j-1] += dp[k-1][i][j]*e;
31                         dp[k][i+1][j] += dp[k-1][i][j]*c;
32                         dp[k][i+1][j+1] += dp[k-1][i][j]*d;
33                     }
34                     else if(j-1>=1&&i==n)
35                     {
36                         dp[k][i][j-1] += dp[k-1][i][j];
37                     }
38                 }
39             }
40         }
41         double res = 0;
42         for(i=1;i<=2*(n-1);i++)
43         {
44             res+=dp[i][n][1]*i;
45         }
46         printf("%.2lf\n",res);
47     }
48     return 0;
49 }
View Code

三、第A题,向量旋转

A - Problem A:Rescue The Princess
【题解】:
给你平面上两个点A、B求点C,是的A、B、C逆时针成等边三角形
向量的旋转:
【code1】:
 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 double xx1,yy1,xx2,yy2;  
 7   
 8 int main()  
 9 {  
10     int T;  
11     scanf("%d",&T);  
12     while (T--)  
13     {  
14         scanf("%lf%lf%lf%lf",&xx1,&yy1,&xx2,&yy2);  
15         double tx = xx2 - xx1;  
16         double ty = yy2 - yy1;  
17   
18         double x = tx*(1.0/2.0) - ty*(sqrt(3.0)/2.0) + xx1;  
19         double y = ty*(1.0/2.0) + tx*(sqrt(3.0)/2.0) + yy1;  
20         printf("(%.2lf,%.2lf)\n",x,y);  
21     }  
22     return 0;  
23 }  
View Code

不会向量旋转,直接解方程方法做:

【code2】:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #define exb 1e-6
  6 #define PI acos(-1.0)
  7 using namespace std;
  8 struct node
  9 {
 10     double x,y;
 11 };
 12 
 13 
 14 double judge(node a ,node b)
 15 {
 16     return (a.x*b.y-a.y*b.x);
 17 }
 18 
 19 double dist(double x1,double y1,double x2,double y2)
 20 {
 21     return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
 22 }
 23 
 24 int main()
 25 {
 26     int t;
 27     scanf("%d",&t);
 28     while(t--)
 29     {
 30         double x1,y1,x2,y2;
 31         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 32         double xx=(x1+x2)/2.0;
 33         double yy=(y1+y2)/2.0;
 34         double dd=dist(x1,y1,x2,y2);
 35         if(fabs(y1-y2)<exb)
 36         {
 37             double yy1=y1+dd*sin(PI/3.0);
 38             double yy2=y1-dd*sin(PI/3.0);
 39             node ab,ac;
 40             ab.x=x2-x1;
 41             ab.y=y2-y1;
 42             ac.x=xx-x1;
 43             ac.y=yy1-y1;
 44 
 45             if(judge(ab,ac)>0)
 46             {
 47                 printf("(%.2f,%.2f)\n",xx,yy1);
 48             }
 49             else
 50             {
 51                 printf("(%.2f,%.2f)\n",xx,yy2);
 52             }
 53         }
 54         else
 55         {
 56             if(fabs(x1-x2)<exb)
 57             {
 58                 double xx1=x1+dd*sin(PI/3.0);
 59                 double xx2=x1-dd*sin(PI/3.0);
 60                 node ab,ac;
 61                 ab.x=x2-x1;
 62                 ab.y=y2-y1;
 63                 ac.x=xx1-x1;
 64                 ac.y=yy-y1;
 65                 if(judge(ab,ac)>0)
 66                 {
 67                     printf("(%.2f,%.2f)\n",xx1,yy);
 68                 }
 69                 else
 70                 {
 71                     printf("(%.2f,%.2f)\n",xx2,yy);
 72                 }
 73             }
 74             else
 75             {
 76                 double k=-(x1-x2)/(y1-y2);
 77                 double pp=atan(k);
 78                 if(pp>PI/2.0)
 79                 pp=PI-pp;
 80                 k=tan(pp);
 81                 double b=yy-(k*xx);
 82                 double dd1=dd*sin(PI/3.0);
 83                 double xx1=sqrt(dd1*dd1/(k*k+1.0));
 84                 double yy1=k*xx1;
 85                 double xx2=-sqrt(dd1*dd1/(k*k+1.0));
 86                 double yy2=k*xx2;
 87                 node ab,ac;
 88                 ab.x=x2-x1;
 89                 ab.y=y2-y1;
 90                 ac.x=xx+xx1-x1;
 91                 ac.y=yy+yy1-y1;
 92                 if(judge(ab,ac)>0)
 93                 {
 94                 printf("(%.2f,%.2f)\n",xx+xx1,yy+yy1);
 95                 }
 96                 else
 97                 printf("(%.2f,%.2f)\n",xx+xx2,yy+yy2);
 98             }
 99         }
100     }
101     return 0;
102 }
View Code

四、第B题,听说可以暴力BFS过,我们队用的 强连通分量+缩点重构图+拓扑排序

Problem B:Thrall’s Dream

【题解】:
  给定n个点,m条有向边,求解任意两点是否可达。也就是 u->v  or  v->u 问题
【code】:
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #define N 2005
  5 #define M 10005
  6 using namespace std;
  7 struct edges
  8 {
  9     int u,v,next;
 10 };
 11 edges mye[M];
 12 edges cj[M];
 13 int head[N];
 14 int myhead[N];
 15 int cnt;
 16 int cntcnt;
 17 int cc,gg;
 18 int dfn[N],low[N],Belong[N],Stap[N];
 19 bool ff[N];
 20 int visitNum,ct,Stop;
 21 bool flag[N];
 22 int id[N],od[N];
 23 void addEdge(int x,int y)
 24 {
 25     mye[cnt].u=x;
 26     mye[cnt].v=y;
 27     mye[cnt].next=head[x];
 28     head[x]=cnt++;
 29 }
 30 
 31 void Add(int x,int y)
 32 {
 33     cj[cntcnt].u=x;
 34     cj[cntcnt].v=y;
 35     cj[cntcnt].next=myhead[x];
 36     myhead[x]=cntcnt++;
 37 }
 38 
 39 int n,m;
 40 void init()
 41 {
 42     scanf("%d%d",&n,&m);
 43     memset(head,-1,sizeof(head));
 44     memset(myhead,-1,sizeof(myhead));
 45     cnt=1;
 46     cntcnt=1;
 47     for(int i=0;i<m;i++)
 48     {
 49         int x,y;
 50         scanf("%d%d",&x,&y);
 51         addEdge(x,y);
 52     }
 53     memset(dfn,0,sizeof(dfn));
 54     memset(low,0,sizeof(low));
 55     memset(Belong,0,sizeof(Belong));
 56     memset(Stap,0,sizeof(Stap));
 57     memset(flag,false,sizeof(flag));
 58     memset(id,0,sizeof(id));
 59     memset(od,0,sizeof(od));
 60 
 61 }
 62 
 63 void tarjan(int i)
 64 {
 65     int y;
 66     Stap[++Stop]=i;
 67     flag[i]=true;
 68     dfn[i]=low[i]=++visitNum;
 69     for(int j=head[i];j!=-1;j=mye[j].next)
 70     {
 71         y=mye[j].v;
 72         if(!dfn[y])
 73         {
 74             flag[y]=true;
 75             tarjan(y);
 76             low[i]=min(low[i],low[y]);
 77         }
 78         else if(flag[y])
 79         low[i]=min(low[i],dfn[y]);
 80     }
 81     if(low[i]==dfn[i])
 82     {
 83         ct++;
 84         do
 85         {
 86             y=Stap[Stop--];
 87             Belong[y]=ct;
 88             flag[y]=false;
 89         }while(y!=i);
 90     }
 91 }
 92 
 93 void dfs(int x,int len)
 94 {
 95     if(myhead[x]==-1 || len>=ct)
 96     {
 97         if(len>gg)
 98         gg=len;
 99         return;
100     }
101     for(int i=myhead[x];i!=-1;i=cj[i].next)
102     {
103         int y=cj[i].v;
104         if(!ff[y])
105         {
106             ff[y]=true;
107             dfs(y,len+1);
108             ff[y]=false;
109         }
110     }
111 }
112 void solve()
113 {
114     visitNum=ct=Stop=0;
115     for(int i=1;i<=n;i++)
116     {
117         if(!dfn[i])
118         tarjan(i);
119     }
120     if(ct==1)
121     {
122         printf("Case %d: Kalimdor is just ahead\n",cc++);
123         return;
124     }
125     for(int i=1;i<=n;i++)
126     {
127         for(int j=head[i];j!=-1;j=mye[j].next)
128         {
129             int y=mye[j].v;
130             int u=Belong[i];
131             int v=Belong[y];
132             if(u!=v)
133             {
134                 od[u]++;
135                 id[v]++;
136                 Add(u,v);
137             }
138         }
139     }
140     int ans1=0,ans2=0;
141     int temp=0;
142     for(int i=1;i<=ct;i++)
143     {
144         if(od[i]==0)
145         {
146             ans1++;
147         }
148         if(id[i]==0)
149         {
150             ans2++;
151             temp=i;
152         }
153     }
154     if(ans1>1 || ans2>1)
155     {
156          printf("Case %d: The Burning Shadow consume us all\n",cc++);
157          return;
158     }
159     memset(ff,false,sizeof(ff));
160     gg=0;
161     dfs(temp,1);
162     if(gg!=ct)
163     {
164         printf("Case %d: The Burning Shadow consume us all\n",cc++);
165 
166     }
167     else
168     {
169         printf("Case %d: Kalimdor is just ahead\n",cc++);
170     }
171     return;
172 }
173 int main()
174 {
175     int t;
176     scanf("%d",&t);
177     cc=1;
178     while(t--)
179     {
180         init();
181         solve();
182     }
183     return 0;
184 }
View Code

五、F题

Problem F:Alice and Bob

【题解】:

给出一个多项式:(a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1)

输入P,求X^p 前边的系数。

【code】:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 int a[10086];
 6 int main()
 7 {
 8     long long sb,p;
 9     int t;
10     int n;
11     int q;
12     while(scanf("%d",&t)!=EOF)
13     {
14         while(t--)
15         {
16             scanf("%d",&n);
17             int i;
18             for(i=0;i<n;i++)
19             {
20                 scanf("%d",&a[i]);
21             }
22             scanf("%d",&q);
23             while(q--)
24             {
25                 scanf("%lld",&p);
26                 long long sb=1;
27                 for(i=0;i<n&&p!=0;i++)
28                 {
29                     if(p%2==1)
30                     {
31                         sb*=a[i];
32                         sb%=2012;
33                     }
34                     p/=2;
35                 }
36                 if(p==0)
37                     printf("%lld\n",sb);
38                 else
39                     printf("0\n");
40             }
41         }
42     }
43     return 0;
44 }
View Code

六:E题
Problem E:Mountain Subsequences

【code】:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string.h>
 4 using namespace std;
 5 char sb[100086];
 6 int dp[100086];
 7 int ha[30];
 8 int main()
 9 {
10     int n;
11     while(scanf("%d",&n)!=EOF)
12     {
13         int i,j,x;
14         long long max,s;
15         scanf("%s",sb);
16         memset(ha,0,sizeof(ha));
17         for(i=0;i<n;i++)
18         {
19             x=sb[i]-'a';
20             dp[i]=0;
21             for(j=0;j<x;j++)
22             {
23                 dp[i]+=ha[j];
24                 dp[i]%=2012;
25             }
26             ha[x]+=dp[i]+1;
27             ha[x]%=2012;
28         }
29       /*  for(i=n-1;i>=0;i--)
30         {
31             printf("%lld ",dp[i]);
32         }*/
33        // printf("\n");
34         max=0;
35         memset(ha,0,sizeof(ha));
36         for(i=n-1;i>=0;i--)
37         {
38             x=sb[i]-'a';
39             s=0;
40             for(j=0;j<x;j++)
41             {
42                 s+=ha[j];
43                 s%=2012;
44             }
45             ha[x]+=s+1;
46             ha[x]%=2012;
47             max+=s*dp[i];
48             max%=2012;
49            // printf("%lld ",s);
50         }
51         //printf("\n");
52         printf("%lld\n",max);
53     }
54     return 0;
55 }
View Code

 七、H题

Problem H:Boring Counting

题解地址:http://www.cnblogs.com/crazyapple/p/3259648.html

转载于:https://www.cnblogs.com/crazyapple/p/3256803.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值