2015 Syrian Private Universities Collegiate Programming Contest 题解

题目在这里>_<

发现这场比赛在网上没有完整的题解,甚至连题目代码都没人贴出来(大概是因为题目太水了吧。。。)。所以宝宝就来写个题解,也就当作成长记录了233333

 

A. Window

题意很简单,给出n组x,y,求x*y的值

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 int main()
 5 {
 6     int n;
 7     long long x,y;
 8     scanf("%d",&n);
 9     while(n--)
10     {
11         scanf("%I64d%I64d",&x,&y);
12         printf("%I64d\n",x*y);
13     }
14     return 0;
15 }
View Code

 

 

B. Paper Game

两个人撕纸片玩,会发现其实能够撕的次数就是x*y,所以就很简单啦^_^

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 int main()
 5 {
 6     int t;
 7     int x,y;
 8     scanf("%d",&t);
 9     while(t--)
10     {
11         scanf("%d%d",&x,&y);
12         if((x*y)&1)
13             printf("Hussain\n");
14         else
15             printf("Hasan\n");
16     }
17     return 0;
18 }
View Code

 

 

C. Rectangles

计数,由于数据范围比较小,O(n)就能过了,根本不需要树状数组线段树神马的。把题目改为输入i,j,k,s再把数据范围改大一点,就需要二维树状数组了。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int Nmax=105;
 5 int high[Nmax];
 6 int t,n,z,x,y,ans;
 7 void init()
 8 {
 9     ans=0;
10     for(int i=0;i<Nmax;i++)
11         high[i]=0;
12 
13 }
14 
15 int main()
16 {
17     //freopen("c.in","r",stdin);
18     scanf("%d",&t);
19     while(t--)
20     {
21         init();
22         scanf("%d",&n);
23         while(n--)
24         {
25             scanf("%d%d%d",&z,&x,&y);
26             for(int i=z+1;i<=x;i++)
27                 high[i]=max(high[i],y);
28         }
29         for(int i=1;i<Nmax;i++)
30             ans+=high[i];
31         printf("%d\n",ans);
32     }
33     return 0;
34 }
View Code

 

 

D. Sequences

求元素间恰好只差1的最长上升子序列,英语渣表示读题的时候没读懂一定要只差1,然后各种看不懂样例2333333  我们知道条件限制越多就越好写,所以必须只差1的话,用dp[i]记录到值为i的元素的最长上升子序列,因此dp[i]=max(dp[i],dp[i-1]+1),O(n)水过。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int Nmax=20005;
 5 int dp[Nmax];
 6 int t,n,x,ans;
 7 int main()
 8 {
 9     //freopen("d.in","r",stdin);
10     scanf("%d",&t);
11     while(t--)
12     {
13         scanf("%d",&n);
14         ans=0;
15         for(int i=0;i<Nmax;i++)
16             dp[i]=0;
17         for(int i=1;i<=n;i++)
18         {
19             scanf("%d",&x);
20             dp[x]=max(dp[x],dp[x-1]+1);
21             ans=max(ans,dp[x]);
22         }
23         printf("%d\n",ans);
24     }
25     return 0;
26 }
View Code

 

 

E. Napoléon

问在8*8的棋盘上,一个只能斜着走的棋子从某点到另一点的最小步数。

只能斜着走的话,显然(x+y)的奇偶性相同才能互相到达。虽然是斜着走,但是每次都能向目标方向靠近一个单位,所以最小步数就是max(|x1-x2|,|y1-y2|) 。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 using namespace std;
 5 const int Nmax=25;
 6 int dis[Nmax][Nmax];
 7 int n,t;
 8 int xs,ys,xe,ye;
 9 int get_num(int x,int y)
10 {
11     return (x-1)*n+y;
12 }
13 int abs(int x)
14 {
15     if(x<0)
16         return -x;
17     return x;
18 }
19 int main()
20 {
21     //freopen("e.in","r",stdin);
22     scanf("%d%d",&t,&n);
23     while(t--)
24     {
25         scanf("%d%d%d%d",&xs,&ys,&xe,&ye);
26         xs++,ys++,xe++,ye++;
27         // printf("%d %d %d %d\n",xs,ys,xe,ye);
28         // printf("%d %d\n",(xs+ys)&1,(xe+ye)&1);
29         if( ((xs+ys)&1)!=((xe+ye)&1) )
30             printf("can't reach!\n");
31         else
32             printf("%d\n",max( abs(xs-xe),abs(ys-ye) ));
33     }
34     return 0;
35 }
View Code

 

 

F. The Best Strategy

又死在了英语上ψ(╰_╯) 做了这题我才知道罚时是怎么算的。。。然而题目里没告诉罚时怎么算,所以又是看不懂样例系列。原来总罚时就是每道题在比赛中的完成时间之和。所以排个序模拟一下就好了。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int Nmax=305;
 5 int num[Nmax];
 6 int sum,ans,number,now;
 7 void init()
 8 {
 9     sum=ans=number=now=0;
10 }
11 
12 int main()
13 {
14     int t,n;
15     //freopen("f.in","r",stdin);
16     scanf("%d",&t);
17     for(int k=1;k<=t;k++)
18     {
19         scanf("%d",&n);
20         init();
21         for(int i=1;i<=n;i++)
22             scanf("%d",&num[i]);
23         sort(num+1,num+n+1);
24         for(int i=1;i<=n;i++)
25         {
26             if(now+num[i]<=300)
27             {
28                 now=now+num[i];
29                 sum+=now;
30                 number++;
31             }
32             else
33                 break;    
34         }    
35         printf("Case %d: %d %d\n",k,number,sum);
36     }
37 }
View Code

 

 

G. Cutie Pie

找到一堆字符里面的“pie”,思路很简单,暴力BFS就好啦~

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 using namespace std;
 5 const int Nmax=25;
 6 char map[Nmax][Nmax];
 7 int t,n,m,nowx,nowy,kkk,nowxx,nowyy;
 8 int dx[]={-1,-1,-1, 0,0, 1,1,1};
 9 int dy[]={-1, 0, 1,-1,1,-1,0,1};
10 struct  Node
11 {
12     int x;
13     int y;
14 }p;
15 queue<Node> q;
16 
17 int get_num(int x,int y)
18 {
19     return (x-1)*m+y;
20 }
21 
22 void init()
23 {
24     while(!q.empty())
25         q.pop();
26 }
27 
28 int main()
29 {
30     //freopen("g.in","r",stdin);
31     scanf("%d",&t);
32     while(t--)
33     {
34         scanf("%d%d",&n,&m);
35         init();
36         for(int i=1;i<=n;i++)
37         {
38             for(int j=1;j<=m;j++)
39             {
40                 getchar();
41                 map[i][j]=getchar();
42                 if(map[i][j]=='p')
43                     q.push((Node){i,j});
44             }
45         }
46         // for(int i=1;i<=n;i++)
47         // {
48         //     for(int j=1;j<=m;j++)
49         //         printf("%c ",map[i][j]);
50         //     printf("\n");
51         // }
52         // while(!q.empty())
53         // {
54         //     p=q.front();
55         //     q.pop();
56         //     printf("%d %d\n",p.x,p.y);
57         // }
58         int ans=0;
59         while(!q.empty())
60         {
61             if(ans)
62                 break;
63             p=q.front();
64             q.pop();
65             for(int i=0;i<8;i++)
66             {
67                 if(ans)
68                     break;
69                 nowx=p.x+dx[i],nowy=p.y+dy[i];
70                 kkk=get_num(nowx,nowy);
71                 if(kkk>=1 && kkk<=n*m && map[nowx][nowy]=='i')
72                 {
73                     for(int j=0;j<8;j++)
74                     {
75                         nowxx=nowx+dx[j],nowyy=nowy+dy[j];
76                         kkk=get_num(nowxx,nowyy);
77                         if(kkk>=1 && kkk<=n*m && map[nowxx][nowyy]=='e')
78                         {
79                             ans=1;
80                             break;
81                         }
82                     }
83                 }
84             }
85         }
86         if(ans)
87             printf("Cutie Pie!\n");
88         else
89             printf("Sorry Man\n");
90     }
91     return 0;
92 }
View Code

 

 

H. Weekend

问一个人从起点到终点接上所有朋友的最短时间。先把每两个点间的最短距离求出来,再对所有的朋友点跑一个记忆化搜索。因为朋友数很少,状态压缩一下记录所有的状态,再用dp[i][j]记录到点i时状态j的最短时间,就搞定啦ヾ(*´▽‘*)ノ 然而我居然漏写了一个等号,然后一直TLE 23333

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int Nmax=1005;
 5 const int INF=1e9;
 6 int ans,ans_min;
 7 int dis[Nmax][Nmax];
 8 int map[Nmax][Nmax];
 9 int x,y,w,n,m,f;
10 int num[Nmax];
11 int book[Nmax],step;
12 
13 void init()
14 {
15     ans=0;
16     step=0;
17     ans_min=INF;
18     for(int i=1;i<=n;i++)
19         for(int j=1;j<=n;j++)
20             dis[i][j]=INF;
21     for(int i=1;i<=n;i++)
22             dis[i][i]=num[i]=book[i]=0;
23 }
24 
25 void dfs(int now)
26 {
27     if(now==f+2)
28     {
29         if(step==f+2)
30             ans_min=min(ans_min,ans);
31         return;
32     }
33 
34     for(int i=1;i<=f+2;i++)
35     {
36         if(dis[num[now]][num[i]]<INF)
37         {
38             if(!book[i])
39             {
40                 ans+=dis[num[now]][num[i]];
41                 step++;
42                 book[i]=1;
43                 dfs(i);
44                 ans-=dis[num[now]][num[i]];    
45                 step--,book[i]=0;
46             }
47             else
48             {
49                 ans+=dis[num[now]][num[i]];
50                 dfs(i);
51                 ans-=dis[num[now]][num[i]];    
52             }
53             
54         }
55     }
56 }
57 
58 int main()
59 {
60     freopen("h.in","r",stdin);
61     int t;
62     scanf("%d",&t);
63     for(int k=1;k<=t;k++)
64     {
65         scanf("%d%d%d",&n,&m,&f);
66         init();
67         printf("Case %d: \n",k);
68         while(m--)
69         {
70             scanf("%d%d%d",&x,&y,&w);
71             dis[x][y]=dis[y][x]=map[x][y]=map[y][x]=w;    
72         }
73         for(int tmp=1;tmp<=n;tmp++)
74         {
75             for(int i=1;i<=n;i++)
76             {
77                 for(int j=1;j<=n;j++)
78                 {
79                     if(dis[i][tmp]+dis[tmp][j]<dis[i][j])
80                         dis[i][j]=dis[i][tmp]+dis[tmp][j];
81                 }
82             }
83         }
84         num[1]=1;
85         book[1]=1,step++;
86         for(int i=2;i<=f+1;i++)
87             scanf("%d",&num[i]);
88         num[f+2]=n;
89         dfs(1);
90         printf("%d\n",ans_min);
91     }
92     return 0;
93 }
View Code

 

 

I. Playing With Strings

模拟模拟!

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <string.h>
 4 using namespace std;
 5 const int Nmax=1005;
 6 char ans[Nmax];
 7 int n,t,now;
 8 int num[26];
 9 char s[Nmax];
10 char c;
11 void init()
12 {
13     now=1;
14     for(int i=0;i<=n+1;i++)
15         ans[i]='\0';
16     for(int i=0;i<26;i++)
17         num[i]=0;
18     for(int i=0;i<n;i++)
19     {
20         c=s[i];
21         num[c-'a']++;
22     }
23     int ct=0;
24     for(int i=0;i<26;i++)
25     {
26         if(num[i]&1)
27             ct++;
28     }
29     if(ct>1)
30     {
31         printf("impossible\n");
32         return;
33     }
34     for(int i=0;i<26;i++)
35     {
36         int kkkk=1;
37         kkkk=0;
38         if(num[i]&1)
39             ans[(n>>1)+1]=i+'a',num[i]--;
40         while( (num[i]-2)>=0 )
41         {
42             ans[now]=ans[n+1-now]=i+'a';
43             num[i]-=2;
44             now++;
45         }
46         
47     }
48     puts(ans+1);
49 }
50 
51 int main()
52 {
53     //freopen("i.in","r",stdin);
54     scanf("%d",&t);
55     getchar();
56     while(t--)
57     {
58         scanf("%s",s);
59         n=strlen(s);
60         init();
61     }
62     return 0;
63 }
View Code

 

 

J. Good Coins

求gcd(i,j)是否为1。所以标程当然是gcd了,然而数据太水,所以用超慢超蠢的无限减法写法过了23333

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 int x,y;
 5 int t;
 6 
 7 int make(int a,int b)
 8 {
 9     if(a<0 || b<0)
10         return 0;    
11     if(a==1 || b==1)
12         return 1;
13     if(a<b)
14         return make(b,a);
15     if(a==b)
16         return 0;
17     return make(a-b,b);
18 }
19 
20 int main()
21 {
22     //freopen("j.in","r",stdin);
23     scanf("%d",&t);
24     while(t--)
25     {
26         scanf("%d%d",&x,&y);
27         if(make(x,y))
28             printf("GOOD\n");
29         else
30             printf("NOT GOOD\n");
31     }
32     return 0;
33 }
View Code

 

 

K. Clash Of Snakes

求在n*m的格子上,1*s和1*k的长条互不重叠的摆法个数。原问题是有方向的,但是没关系,我们只要在没方向的方案数上乘4就是答案了。

用容斥原理,先求出来单独摆s和摆k的个数,再求出重叠的个数,一减就是答案了。然而要注意的是,模运算中,模完再做减法可能会出负数,所以最后要特判一下(就是因为这个负数,一直wa在第二个点,呜呜呜)。

由于本人比较懒,所以写了ll类型用来求模,虽然在相同写法上速度可能会慢点,但是容易检查而且不易写错,还是值得的。最终还是只有15ms就通过啦ヾ(o◕∀◕)ノヾ

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int Mod=1000000007;
 5 
 6 struct ll
 7 {
 8     long long x;
 9     ll() {x=0;}    
10     ll(long long tttt) {x=tttt;}
11 
12     ll operator + (ll b)
13     {
14         ll c;
15         c.x=(x+b.x)%Mod;
16         return c;
17     }
18 
19     ll operator * (ll b)
20     {
21         ll c;
22         c.x=(x*b.x)%Mod;
23         return c;
24     }
25 
26     ll operator -(ll b)
27     {
28         ll c;
29         c.x=(x-b.x)%Mod;
30         return c;
31     }
32 
33 };
34 
35 ll get(ll n,ll m,ll k)
36 {
37     ll get_value(0);
38     if(k.x<=m.x && k.x<=n.x)
39         return (m-k+1)*n + (n-k+1)*m;
40     if(k.x>m.x && k.x<=n.x)
41         return (n-k+1)*m;
42     if(k.x>n.x && k.x<=m.x)
43         return (m-k+1)*n;
44     return get_value;
45     
46 }
47 
48 ll max(ll a,ll b)
49 {
50     if(a.x>=b.x)
51         return a;
52     else
53         return b;
54 }
55 
56 ll min(ll a,ll b)
57 {
58     if(a.x<=b.x)
59         return a;
60     else
61         return b;
62 }
63 
64 int main()
65 {
66     //freopen("k.in","r",stdin);
67     int t;
68     ll two(2),four(4),one(1),eight(8);
69     scanf("%d",&t);
70     long long tmpn,tmpm,tmps,tmpk;
71     for(int i=1;i<=t;i++)
72     {    
73         scanf("%I64d%I64d%I64d%I64d",&tmpn,&tmpm,&tmps,&tmpk);
74         ll n(tmpn),m(tmpm),s(tmps),k(tmpk);
75         ll l=max(k,s);
76         ll r=min(k,s);
77         ll ans=(two*m*n-(m+n)*(k-one))*(two*m*n-(m+n)*(s-one));
78         ll a=min(m,k+s-one);
79         ll b=min(n,k+s-one);
80         ans=ans-k*s*( (n-s+one)*(m-k+one)+(n-k+one)*(m-s+one) );
81         ans=ans-(m-l+one)*n*(l-r+one)-(n-l+one)*m*(l-r+one);
82         ans=ans-n*(a-l)*( two*(m+one)-(a+l+one) );
83         ans=ans-m*(b-l)*( two*(n+one)-(b+l+one) );
84         ans=ans*four;
85         if(ans.x<0)
86                 ans.x+=Mod;
87         printf("Case %d: %I64d\n",i,ans.x);
88     }
89     return 0;
90 }
View Code

 

posted @ 2016-11-01 09:54  BBBob  阅读(678)  评论(0编辑  收藏  举报