第十七届浙大城市学院程序设计竞赛(同步赛)

https://ac.nowcoder.com/acm/contest/5954#question

A

Sumo and Keyboard-Cat

签到题

一个字符串里面只包含大小写字母,初始为大写字母,一只小猫按了键盘切换大小写,问切换了几次?

只要遍历一下字符串,记录当前的大小写状态,若不同,ans++,状态切换。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const int mod=911451407;
24 const int N=100000+50;
25 char s[N];
26 int main()
27 {
28     scanf("%s",s+1);
29     int n=strlen(s+1);
30     int ans=0,f=1;
31     for(int i=1;i<=n;i++)
32     {
33         if(s[i]>='A'&&s[i]<='Z')
34             s[i]=1;
35         else    s[i]=-1;
36     }
37     for(int i=1;i<=n;i++)
38     {
39         if(s[i]!=f)
40         {
41             ans++;
42             f=-f;
43         }
44     }
45     printf("%d\n",ans);
46 
47     return 0;
48 }
View Code
B Sumo and His Followers

签到题

有n个人在排队,每个人需要的时间为ti,求最小平均等待时间为多少。

当前面人的时间越短,等待时间就越短。排序一下就可以了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const int mod=911451407;
24 const int N=100000+50;
25 int T,n;
26 ll a[N],sum[N];
27 int main()
28 {
29     scanf("%d",&T);
30     while(T--)
31     {
32         scanf("%d",&n);
33         for(int i=1;i<=n;i++)
34         {
35             scanf("%lld",&a[i]);
36             sum[i]=0;
37         }
38         sort(a+1,a+n+1);
39         for(int i=1;i<=n;i++)
40             sum[i]=sum[i-1]+a[i];
41         ll ans=0;
42         for(int i=2;i<=n;i++)
43             ans+=sum[i-1];
44         double kk=(ans*1.0)/n;
45         printf("%.2lf\n",kk);
46     }
47 
48 
49     return 0;
50 }
View Code
C

Sumo and Virus

简单dp

有一个人被感染了,潜伏期第一天为第一天,小镇上有m个人,问第n天病患个数有多少。

  • 一个病患每天可以传染x个未被感染的人;
  • 潜伏期为7天,期间不发病也不传染别人;
  • 第8天开始发病,并且可以传染;
  • 第14天,被治愈(当天不会传染,且不再具有传染能力);
  • 治愈之后具有抵抗力,不会被传染。 

设f[i]为第i天的病患,a[i]为第i天新增的潜伏人员。

f[i]=f[i-1]+a[i-7]-a[i-13];

m-=a[i-13];

now-=a[i-7];  第i天之前所有的潜伏人员个数.

 

a[i]=min(f[i]*x,m-f[i]-now);

now+=a[i];

今天的病患等于昨天的病患加上前7天增加的潜伏者减去前13天增加的潜伏者

小镇上能感染的人数-已经痊愈的患者,也就是前13天新增加的潜伏者

所有的潜伏人员个数-前7天变成病患的个数

今天能增加的潜伏人员的最大个数

所有的潜伏人员加上今天产生的潜伏人员。

最后,10^10的数据爆int了,我爆哭,不然就过了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const int mod=911451407;
24 const int N=100000+50;
25 int T;
26 ll x,n,m;
27 ll f[N],a[N],ans=0,now=0;
28 int main()
29 {
30     //cout<<(2^0^0)<<endl;
31     scanf("%d",&T);
32     while(T--)
33     {
34          scanf("%lld%lld%lld",&x,&m,&n);
35          for(int i=1;i<=n;i++)
36             a[i]=f[i]=0;
37          ans=0;
38             a[1]=1;
39             now=1;
40             for(int i=8;i<=n;i++)
41             {
42                 f[i]=f[i-1]+a[i-7];
43                 if(i>13&&a[i-13]) {f[i]-=a[i-13];  ans+=a[i-13];}
44 
45                 //a[i]=f[i]*x;
46                 now-=a[i-7];
47                 a[i]=min(f[i]*x,m-ans-f[i]-now);
48                 now=now+a[i];
49 
50                 //cout<<i<<" "<<a[i]<<" "<<f[i]<<endl;
51             }
52             cout<<f[n]<<endl;
53     }
54 
55 
56     return 0;
57 }
View Code

 

D Sumo and Easy Sum

数学题。

 

 

 求极限 lim Sn 

 

 

 然后就变成了求gcd的问题了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const int mod=911451407;
24 const int N=100000+50;
25 int _gcd(int a,int b)
26 {
27     if(b==0)    return a;
28     return _gcd(b,a%b);
29 }
30 int main()
31 {
32     int T,k;
33     scanf("%d",&T);
34     while(T--)
35     {
36         scanf("%d",&k);
37         int a=k*k-k-1;
38         int gcdd=_gcd(k,a);
39         k/=gcdd;    a/=gcdd;
40         if(a==1)    printf("%d\n",k);
41         else    printf("%d/%d\n",k,a);
42     }
43 
44 
45     return 0;
46 }
View Code
F Sumo and Luxury Car

签到题。

有n辆车,每次小明从n辆车中任意选出一个集合,然后再从集合中选出一辆车,求方案个数。

集合不同算不同方案,同一集合选不同车算不同方案。

1Cn1+2Cn2+3Cn3+……=n*2^(n-1);

快速幂运算就好了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const ll mod=1e9+7;
24 const int N=100000+50;
25 int T;
26 ll n;
27 ll _pow(ll a,ll b)
28 {
29     ll res=1;
30     while(b)
31     {
32         if(b&1) res=(res*a)%mod;
33         b>>=1;
34         a=(a*a)%mod;
35     }
36     return res;
37 }
38 int main()
39 {
40     scanf("%d",&T);
41     while(T--)
42     {
43         scanf("%lld",&n);
44         ll ans=(n*_pow(2,n-1))%mod;
45         printf("%lld\n",ans);
46 
47     }
48 
49 
50     return 0;
51 }
View Code
H Sumo and Electricity(Easy)

有n个点m条边。每个点都有权值wi,其中仅有一个点权值为-1,代表任意。

每条边的权值为两个点的异或值,求所有边的权值最小和,以及所有点的权值最小和。

我们把所有与权值为-1的点的另外一个点放进一个集合里面。

求a1^x+a2^x+a3^x+……的值最小。

由异或我们得知,把每个ai分解成二进制。

每一位的1大于0的个数时,我们取1

当0的个数大于等于1的个数时,取0

这就是x的最小值。

最后只要把所有边的异或值加起来,和点的值加起来就可了

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const int mod=911451407;
24 const int N=100000+50;
25 int n,m;
26 ll w[550];
27 int xx[2100],yy[2100],kk;
28 int ans[5][40];
29 void check(ll x)
30 {
31     int len=0;
32     while(x)
33     {
34         if(x&1) ans[1][len]++;
35         else    ans[0][len]++;
36         len++;
37         x/=2;
38     }
39     for(int i=len;i<31;i++)
40         ans[0][i]++;
41     return;
42 }
43 int main()
44 {
45     scanf("%d%d",&n,&m);
46     ll summ=0;
47     for(int i=1;i<=n;i++)
48     {
49         scanf("%lld",&w[i]);
50         if(w[i]==-1)    {kk=i;  continue;}
51         summ+=w[i];
52     }
53     for(int i=1;i<=m;i++)
54     {
55         scanf("%d%d",&xx[i],&yy[i]);
56         if(xx[i]==kk)   check(w[yy[i]]);
57         if(yy[i]==kk)   check(w[xx[i]]);
58     }
59     ll x=0,res=1;
60     for(int i=0;i<31;i++)
61     {
62         if(ans[1][i]>ans[0][i])    x+=res;
63         res*=2;
64         //cout<<ans[1][i]<<" "<<ans[0][i]<<endl;
65     }
66     w[kk]=x;
67     //cout<<x<<endl;
68     ll anss=0;
69     for(int i=1;i<=m;i++)
70     {
71         anss+=w[xx[i]]^w[yy[i]];
72     }
73     printf("%lld\n%lld\n",anss,x+summ);
74 
75 
76     return 0;
77 }
View Code
L Sumo and Coins

有n个硬币,有a个向上,b个向下。求每次翻转n-1个硬币,求是否有可能全部硬币向下或者向上。

翻转n-1的硬币相当于翻转1个硬币,然后向上向下值相反一次。

若有4个 0000,全向上,我们有可能做出任何状态。(1111 1010 1110)等等

若有5个00000,我们不可能使所有都变为1 不可能达到11111状态。

当n为偶数的时候,ALL

当n为奇数的时候

  当1的个数为偶数的时候 UP

  else  DOWN

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <set>
 6 #include <queue>
 7 #include <stack>
 8 #include <string>
 9 #include <cstring>
10 #include <vector>
11 #include <map>
12 #include<ctime>
13 #include <unordered_map>
14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
16 #define lson  l ,mid ,pos<<1
17 #define rson mid+1 ,r ,pos<<1|1
18 using namespace std;
19 typedef long long ll ;
20 typedef pair<int ,int> pii;
21 typedef pair<ll ,int> pli;
22 const ll inf = 0x3f3f3f3f;
23 const int mod=911451407;
24 const int N=100000+50;
25 int T,n,a,b;
26 
27 int main()
28 {
29     scanf("%d",&T);
30     while(T--)
31     {
32         scanf("%d%d%d",&n,&a,&b);
33         if(n%2==0)  puts("ALL");
34         else
35         {
36             if(b%2==0)  puts("UP");
37             else    puts("DOWN");
38         }
39         
40     }
41 
42 
43     return 0;
44 }
View Code
J Sumo and Balloon

数学题。

三维平面上,有一个平面,有一个点,从这个点开始吹气球,每秒吹L气体。保证吹气球的方向垂直于墙。

求什么时候气球会炸裂。

求点与平面的距离l=2*r

3/4*r^3*pi<=L*t

求t

最主要的就是求点与平面的距离。用向量法来求。等明天看看定理qaq

 

E Sumo and Group Activity

 这个人想开m场party,有n个地点可以选择,分别为pi(pi<=1e9)

已知pi!=pi-1,这party的地点不能和前一个相同。

第0次party的地点为a,家为b。

当前地点到下一个地点的距离要严格小于当前地到家的距离。

题目说可以选择自己的家作为party的地点,但是通过条件我们得知不可能选择家,具体原因看上一条。

 

我们设f[i][j]为已经开展了i场party,最后地点为j的方案数。

因为每个点的坐标都已经给出了,所以我们可以知道每个点所能达到的左边界l和右边界r

若f[i-1][j]有值,f[i][l] 到 f[i][j-1] 都加上f[i-1][j]   f[i][j+1] 到 f[i][r] 都加上 f[i-1][j]

这样就是n^3的复杂度。

 

我们通过一个差分数组可以优化到n^2

需要注意的点:离散化,差分数组相减取模,a,b的序号和离散化之后不同,左边界和右边界的求法。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <algorithm>
  5 #include <set>
  6 #include <queue>
  7 #include <stack>
  8 #include <string>
  9 #include <cstring>
 10 #include <vector>
 11 #include <map>
 12 #include <ctime>
 13 #include <unordered_map>
 14 #define mem( a ,x ) memset( a , x ,sizeof(a) )
 15 #define p( i ,x ,y ) for( int i = x ; i<=y ;i++ )
 16 #define lson  l ,mid ,pos<<1
 17 #define rson mid+1 ,r ,pos<<1|1
 18 using namespace std;
 19 typedef long long ll ;
 20 typedef pair<int ,int> pii;
 21 typedef pair<ll ,int> pli;
 22 const ll inf = 0x3f3f3f3f;
 23 const ll mod=1e9+7;
 24 const int N=100000+50;
 25 int n,a,b,m,x;
 26 int d[5100];
 27 ll f[5100][5100];
 28 int l[5100],r[5100],lll,rrr,lx,rx;
 29 ll tmp[5100];
 30 int k1,k2;
 31 vector<int>p;
 32 int main()
 33 {
 34     scanf("%d%d%d%d",&n,&a,&b,&m);
 35     a--;    b--;
 36     for(int i=1;i<=n;i++)
 37     {
 38         scanf("%d",&x);
 39         p.push_back(x);
 40     }
 41     k1=p[a];    k2=p[b];
 42     sort(p.begin(),p.end());
 43     for(int i=0;i<n;i++)
 44         d[i]=i;
 45     for(int i=0;i<n;i++)
 46     {
 47         if(k1==p[i])    a=i;
 48         if(k2==p[i])    b=i;
 49     }
 50    // cout<<a<<" "<<b<<endl;
 51     for(int i=0;i<n;i++)
 52     {
 53         if(p[i]<=p[b])
 54         {
 55             lll=2*p[i]-p[b];
 56             lx=upper_bound(p.begin(),p.end(),lll)-p.begin();
 57             l[i]=lx;
 58             rrr=p[b];
 59             rx=lower_bound(p.begin(),p.end(),rrr)-p.begin();
 60             r[i]=rx-1;
 61         }
 62         else
 63         {
 64             lll=p[b];
 65             lx=upper_bound(p.begin(),p.end(),lll)-p.begin();
 66             l[i]=lx;
 67             rrr=2*p[i]-p[b];
 68             rx=lower_bound(p.begin(),p.end(),rrr)-p.begin();
 69             r[i]=rx-1;
 70         }
 71         //cout<<l[i]<<" "<<r[i]<<endl;
 72     }
 73 
 74 
 75     f[0][a]=1;
 76     for(int i=1;i<=m;i++)
 77     {
 78         for(int j=0;j<=n;j++)
 79             tmp[j]=0;
 80         for(int j=0;j<n;j++)
 81             if(f[i-1][j])
 82             {
 83                 if(l[j]<j)
 84                 {tmp[l[j]]+=f[i-1][j];
 85                 tmp[j]-=f[i-1][j];
 86                 }
 87                 if(r[j]>j)
 88                 {tmp[j+1]+=f[i-1][j];
 89                 tmp[r[j]+1]-=f[i-1][j];
 90                 }
 91                 tmp[l[j]]%=mod;
 92                 //tmp[j]%=mod;
 93                 tmp[j]=(tmp[j]+mod)%mod;
 94                 tmp[j+1]%=mod;
 95                 //tmp[r[j]+1]%=mod;
 96                 tmp[r[j]+1]=(tmp[r[j]+1]+mod)%mod;
 97             }
 98         f[i][0]=tmp[0];
 99         for(int j=1;j<=n;j++)
100         {
101             tmp[j]+=tmp[j-1];
102             tmp[j]%=mod;
103             f[i][j]=tmp[j];
104             //cout<<f[i][j]<<" ";
105         }
106         //cout<<endl;
107     }
108     ll ans=0;
109     for(int i=0;i<n;i++)
110     {
111         ans=(ans+f[m][i])%mod;
112     }
113     printf("%lld\n",ans);
114 
115 
116     return 0;
117 }
View Code

 

posted @ 2020-06-06 22:09  kaike  阅读(307)  评论(0编辑  收藏  举报