UPC2018组队训练赛第二场

题目来自 ICPC Japan IISF 2018


 

A题:Income Inequality

输入一串数字,寻找里面小于等于这些数字平均值的个数。


 

B题:Origami

一张正方形的方格纸,只能从左往右,从上往下折叠,折叠t次后有q次询问,每次询问给出的是最终状态下方格的坐标(左下角为(0,0)),代表在这个地方扎个洞,问你把方格纸展开后有多少个洞。每次询问是独立的

输入n,m,t,q(n代表的是宽度、m代表的是高度,t是折叠次数,q是询问次数),对于t次折叠,输入op、p(op==1,表示把左边的p列折到右边;op==2,表示把下边的p行折到上边),对于q次询问,输入x,y(x代表列,y代表行

直接模拟即可。但是要注意2*p可能会大于原来的宽度或高度

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,t,q,mp[100][100],bp[100][100],k;
 4 int main()
 5 {
 6 //    freopen("in.txt","r",stdin);
 7     while(1)
 8     {
 9         scanf("%d%d%d%d",&m,&n,&t,&q);
10         if(m==0&&n==0&&t==0&&q==0)
11                 return 0;
12         for(int i=0;i<=n;i++)
13             for(int j=0;j<=m;j++)
14                 mp[i][j]=1;
15         int op,p;
16         while(t--)
17         {
18             scanf("%d%d",&op,&p);
19             if(op==1)
20             {
21                 if(2*p<=m)
22                 {
23                     for(int i=1;i<=n;i++)
24                     {
25                         for(int j=p+1;j<=2*p;j++)
26                             mp[i][j]+=mp[i][2*p+1-j];
27                     }
28                     for(int i=1;i<=n;i++)
29                         for(int j=1;j<=m-p;j++)
30                             mp[i][j]=mp[i][j+p];
31                     m-=p;
32                 }
33                 else
34                 {
35                     for(int i=1;i<=n;i++){
36                         for(int j=p+1;j<=m;j++)
37                             bp[i][j]=mp[i][j]+mp[i][2*p+1-j];
38                         for(int j=m+1;j<=2*p;j++)
39                             bp[i][j]=mp[i][2*p+1-j];
40                     }
41                     for(int i=1;i<=n;i++)
42                     {
43                         k=0;
44                         for(int j=p+1;j<=2*p;j++)
45                         {
46                             mp[i][++k]=bp[i][j];
47                         }
48                     }
49                     m=p;
50                 }
51             }
52             else
53             {
54                 if(2*p<=n)
55                 {
56                     for(int i=n-2*p+1;i<=n-p;i++)
57                         for(int j=1;j<=m;j++)
58                             mp[i][j]+=mp[2*(n-p)+1-i][j];
59                     n-=p;
60                 }
61                 else
62                 {
63                     k=p;
64                     for(int i=n-p+1;i<=2*(n-p);i++)
65                     {
66                         for(int j=1;j<=m;j++)
67                             bp[i][j]=mp[i][j]+mp[2*(n-p)+1-i][j];
68                     }
69                     for(int i=2*(n-p)+1;i<=n;i++)
70                     {
71                         for(int j=1;j<=m;j++)
72                             bp[i][j]=mp[i][j];
73                     }
74  
75                     for(int i=n-p+1;i<=n;i++){
76                         for(int j=1;j<=m;j++){
77                             mp[k][j]=bp[i][j];
78                         }
79                         k--;
80                     }
81                     n=p;
82                 }
83             }
84         }
85         int x,y;
86         while(q--)
87         {
88             scanf("%d%d",&x,&y);
89             printf("%d\n",mp[n-y][x+1]);
90         }
91     }
92     return 0;
93 }
View Code

 

C题:Skyscraper

输入n,求一个最长的公差为1的等差数列,满足他们的和为n,输出等差数列的第一项和它的长度

由求和公式( 2*a + (k-1) )*k / 2=n.得a=(2*n - k*k +k )/(2*k) ,由于a>1我们可以知道k的范围是1--sqrt(2*n),那么直接从大到小枚举即可,直到找出k满足a为整数

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4  
 5 int main()
 6 {
 7     ll n;
 8     while(1)
 9     {
10         scanf("%lld",&n);
11         if(n==0)
12         {
13             return 0;
14         }
15         ll maxx=sqrt(2*n);
16         ll tmp;
17         for(ll i=maxx;i>=1;i--)
18         {
19             tmp=2*n-i*i+i;
20             if(tmp%(2*i)==0)
21             {
22                 printf("%lld %lld\n",tmp/(2*i),i);
23                 break;
24             }
25         }
26     }
27     return 0;
28 }
View Code

 

D题:Playoff

输入n代表有多少支队伍,已知m组队伍的比赛结果,问能有多少种方式能达到“full playoff”(指的是每个队胜场数一样)

首先预处理一下,如果这个队的胜场数或者败场数达到了要求,就把这个队与其他队的情况相应地设为失败或者胜利。然后就搜索,但直接搜的话会超时。主要是当n=9时,m=0、1、2的情况比较多。我们可以直接输出

搜索部分代码是参考大佬的

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3  
  4 int n,m,f[10][10],r[15],c[15],nn,ans;//0-unknown 1-win 2-lose
  5 int fr[10],fc[10];//r[]代表当前行的胜场数,fr[]代表当前行的败场数,c[]代表当前列的胜场数。fc[]代表当前列的败场数
  6 void dfs(int x,int y)
  7 {
  8     if(x>n)
  9     {
 10         ans++;
 11         return ;
 12     }
 13     if(y>n)
 14     {
 15         dfs(x+1,x+1);
 16         return ;
 17     }
 18     if(r[x]>nn||r[y]>nn)    return ;
 19     if(!f[x][y]&&x!=y)
 20     {
 21         if(r[x]<nn)
 22         {
 23             r[x]++;
 24             f[x][y]=1;
 25             f[y][x]=2;
 26             dfs(x,y+1);
 27             r[x]--;
 28             f[x][y]=f[y][x]=0;
 29         }
 30         if(r[y]<nn)
 31         {
 32             r[y]++;
 33             f[x][y]=2;
 34             f[y][x]=1;
 35             dfs(x,y+1);
 36             r[y]--;
 37             f[x][y]=f[y][x]=0;
 38         }
 39     }
 40     else
 41         dfs(x,y+1);
 42 }
 43 int main()
 44 {
 45 //    freopen("in.txt","r",stdin);
 46     while(1)
 47     {
 48         scanf("%d",&n);
 49         if(n==0)    return 0;
 50         scanf("%d",&m);
 51         nn=(n-1)/2;
 52         int x,y;
 53         memset(f,0,sizeof(f));
 54         memset(fr,0,sizeof(fr));
 55         memset(fc,0,sizeof(fc));
 56         memset(r,0,sizeof(r));
 57         memset(c,0,sizeof(c));
 58         int aa,bb,cc,dd;
 59         if(n==9)  //n==9特判一下
 60         {
 61             if(m==0)    {printf("3230080\n");continue;}
 62             else if(m==1)
 63             {
 64                 scanf("%d%d",&aa,&bb);
 65                 printf("1615040\n");
 66                 continue;
 67             }
 68             else if(m==2)
 69             {
 70                 scanf("%d%d%d%d",&aa,&bb,&cc,&dd);
 71                 if(aa==cc)
 72                 {
 73                     printf("692160\n");
 74                     continue;
 75                 }
 76                 else if(aa==dd||bb==cc)
 77                 {
 78                     printf("922880\n");
 79                     continue;
 80                 }
 81                 else
 82                 {
 83                     printf("807520\n");
 84                     continue;
 85                 }
 86             }
 87         }
 88         while(m--)
 89         {
 90             scanf("%d%d",&x,&y);
 91             f[x][y]=1;
 92             f[y][x]=2;
 93         }
 94  
 95         bool flag=0;
 96         int p=0;
 97         for(int i=1;i<=n;i++)//统计每行每列的状态
 98         {
 99             for(int j=1;j<=n;j++)
100             {
101                 if(f[i][j]==1)
102                     r[i]++,c[j]++;
103                 else if(f[i][j]==2)
104                     fr[i]++,fc[j]++;
105             }
106             if(r[i]>nn||fr[i]>nn)
107             {
108                 flag=1;
109                 break;
110             }
111             p+=r[i];
112         }
113         for(int i=1;i<=n;i++)  //预处理
114         {
115             if(r[i]==nn)
116             {
117                 for(int j=1;j<=n;j++)
118                 {
119                     if(i==j)    continue;
120                     if(!f[i][j])
121                     {
122                         f[i][j]=2;
123                         f[j][i]=1;
124                         fr[i]++;fc[j]++;
125                         r[j]++;c[i]++;
126                     }
127                 }
128             }
129             else if(fr[i]==nn)
130             {
131                 for(int j=1;j<=n;j++)
132                 {
133                     if(i==j)    continue;
134                     if(!f[i][j])
135                     {
136                         f[i][j]=1;
137                         f[j][i]=2;
138                         fr[j]++;fc[i]++;
139                         r[i]++;c[j]++;
140                     }
141                 }
142             }
143         }
144         for(int j=1;j<=n;j++)
145         {
146             if(c[j]==nn)
147             {
148                 for(int i=1;i<=n;i++)
149                 {
150                     if(i==j)    continue;
151                     if(!f[i][j])
152                     {
153                         f[i][j]=2;
154                         f[j][i]=1;
155                         fr[i]++;fc[j]++;
156                         r[j]++;c[i]++;
157                     }
158                 }
159             }
160         }
161         if(flag){printf("0\n");continue;}
162         ans=0;
163         dfs(1,1);
164         printf("%d\n",ans);
165     }
166     return 0;
167 }
View Code

 

转载于:https://www.cnblogs.com/scott527407973/p/9525474.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值