第十七届浙大城市学院程序设计竞赛(同步赛)
https://ac.nowcoder.com/acm/contest/5954#question
A |
签到题
一个字符串里面只包含大小写字母,初始为大写字母,一只小猫按了键盘切换大小写,问切换了几次?
只要遍历一下字符串,记录当前的大小写状态,若不同,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 }
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 }
C |
简单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 }
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 }
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 }
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 }
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 }
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 }