zoukankan      html  css  js  c++  java
  • 寒假练习题解 第五周 2.15-2.21

    每日一练

    2.15

    Problem A Tanya and Postcard

    题意:给两个字符串s和t,求相同字母数,再求剩下字母中仅大小写不同数。

    简析:分别统计两个串的每个字母个数,再按题意计算。

     1 #include<cstdio>
     2 #include<string>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=2e5+1;
     6 int a,b,n,m,i;
     7 char s[N],t[N];
     8 int hs[130],ht[130];
     9 int main(){
    10     scanf("%s %s",s,t);
    11     n=strlen(s);m=strlen(t);
    12     for(i=0;i<n;++i) hs[s[i]]++;
    13     for(i=0;i<m;++i) ht[t[i]]++;
    14     for(char ch='A';ch<='Z';++ch){
    15         int t=min(hs[ch],ht[ch])+min(hs[ch+32],ht[ch+32]);
    16         a+=t;
    17         b+=min(hs[ch]+hs[ch+32],ht[ch]+ht[ch+32])-t;
    18     }
    19     printf("%d %d
    ",a,b);
    20     return 0;
    21 }
    优秀代码

    Problem B Anya and Smartphone

    题意:n个应用,每屏最多k个,应用被运行会前移,要运行m个应用,求最少滑屏和启动次数。

    简析:直接模拟即可。

     1 #include<cstdio>
     2 #define N 100001
     3 int n,m,k,b,i,s;
     4 int a[N],g[N];
     5 long long ans;
     6 int main(){
     7     scanf("%d%d%d",&n,&m,&k);
     8     for(i=0;i<n;i++){
     9         scanf("%d",&a[i]);
    10         g[a[i]]=i;
    11     }
    12     while(m--){
    13         scanf("%d",&b);
    14         s=g[b];
    15         ans+=(s/k+1);
    16         if(s){
    17             int t=a[s];a[s]=a[s-1];a[s-1]=t;
    18             g[a[s]]=s;g[a[s-1]]=s-1;
    19         }
    20     }
    21     printf("%lld
    ",ans);
    22     return 0;
    23 }
    优秀代码

    2.16

    Problem A Drazil and His Happy Friends

    题意:有n个男孩,m个女孩,有些人不开心,有些人开心,在第i天,第i%n 的男孩和 第i%m的女孩一起吃饭,开心的人可以把不开心的人变得开心

    求能否使得所有的男孩女孩都开心

    简析:暴力模拟

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <climits>
     5 #include <cstdlib>
     6 #include <cstring>
     7 using namespace std;
     8 
     9 int main()
    10 {
    11     int n, m, b, g, x[101], y[101], temp;
    12     while(scanf("%d%d", &n, &m) != EOF) {
    13         memset(x, 0, sizeof(x));
    14         memset(y, 0, sizeof(y));
    15         scanf("%d", &b);
    16         for(int i = 0; i < b; ++i) {
    17             scanf("%d", &temp);
    18             x[temp] = 1;
    19         }
    20         scanf("%d", &g);
    21         for(int i = 0; i < g; ++i) {
    22             scanf("%d", &temp);
    23             y[temp] = 1;
    24         }
    25         for(int i = 0; i <= 10000; ++i) {
    26             if(y[i % m] == 1 || x[i % n] == 1) {
    27                 y[i % m] = x[i % n] = 1;
    28             }
    29         }
    30         bool flag = false;
    31         for(int i = 0; i < m; ++i) {
    32             if(y[i] == 0) {
    33                 flag = true;
    34                 break;
    35             }
    36         }
    37         for(int i = 0; i < n; ++i) {
    38             if(x[i] == 0) {
    39                 flag = true;
    40                 break;
    41             }
    42         }
    43         if(!flag) {
    44             printf("Yes
    ");
    45         } else {
    46             printf("No
    ");
    47         }
    48     }
    49     return 0;
    50 }
    优秀代码

    还可以扫一遍在[0,gcd(n,m)] 的区间的人是否都为开心的,因为如果编号为 i 的人开心,那么 满足 x%g = i%g 的x 都将在某一天变得开心

     1 #include<iostream>
     2 using namespace std;
     3 int gcd(int a,int b){
     4     return b == 0?a:gcd(b,a%b);
     5 } 
     6 int temp[105];
     7 int main(){
     8     int n,m,t,b,g,x,y;
     9     cin>>n>>m;
    10     t = gcd(n,m);
    11     cin>>b;
    12     for(int i = 0; i<b; i++){
    13         cin>>x;
    14         temp[x%t] = 1;
    15     }
    16     cin>>g;
    17     for(int i = 0; i<g; i++){
    18         cin>>y;
    19         temp[y%t] = 1;
    20     }
    21     int ans = 0;
    22     for(int i = 0; i<t; i++){
    23         if(temp[i]) ans++;
    24     }
    25     if(ans == t) printf("Yes
    ");
    26     else printf("No
    ");
    27     return 0; 
    28 }
    优秀代码

    Problem B Drazil and Factorial

    题意:定义 F(xyz) = x! * y! * z!,找到最大的uvw 使得 F(uvw) = F(xyz)

    简析:1 != 1!

       2! = 2!

       3! = 3!

         4! = 2! * 2!

         5! = 5!

       6! = 5! * 3!

         7 !=7!

       8! =7! * 2! * 2!* 2!

       9!=7!*3!*3!*2!

    把每一位分解,然后再排下序

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring>  
     4 #include<algorithm>  
     5 using namespace std;
     6 int ss[100005];
     7 char str[20];
     8 int s[10][5]={{0},{0},{2},{3},{3,2,2},{5},{5,3},{7},{7,2,2,2},{7,3,3,2}};
     9 int cmp(int a,int b)
    10 {
    11     return a>b;
    12 }
    13 int main()
    14 {
    15     int  n,i,j,k=0;
    16     scanf("%d",&n);
    17     scanf("%s",&str);
    18     for(i=0;i<n;i++)
    19     {
    20         int a=str[i]-'0';
    21         for(j=0;s[a][j]!=0;j++)
    22         {
    23             ss[k]=s[a][j];
    24             k++;
    25         }    
    26     }
    27     sort(ss,ss+k,cmp);
    28     for(i=0;i<k;i++)
    29     printf("%d",ss[i]);
    30     printf("
    ");    
    31 }
    View Code

    2.17

    Problem A Han Solo and Lazer Gun

    题意:给一个原点和n个其他点,求过原点的最少直线数使得n个点都在直线上。

    简析:由于n很小,可以n2判断每两点是否能共线。

       当然考虑到原点已定,直线仅由斜率确定,也可以扫一遍所有点,记录斜率判重。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<set>
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     set<double> s;
     9     int n,x0,y0,x,y,p=0;
    10     scanf("%d%d%d",&n,&x0,&y0);
    11     for(int i=1;i<=n;i++){
    12         scanf("%d%d",&x,&y);
    13         if(y0!=y){
    14             double t=1.000000*(x0-x)/(y0-y);
    15             s.insert(t);
    16         }
    17         else p=1;
    18     }
    19     printf("%d
    ",s.size()+p);
    20     
    21     return 0;
    22 }
    code from niu

    Problem B Watto and Mechanism

    题意:给一个n个字符串的集合,询问m个字符串,问在集合中是否存在与询问串仅有一个字符不同的等长串。

    简析:这题的做法涉及一些大家没有学习过的姿势,可以先做一个了解。

       做法一:字符串哈希,一份介绍PPT戳这里

           但是我们知道CF是有hack的,如果你的哈希没有冲突处理,场上都可以hack,

           只不过现在赛后数据固定下来了,一些没有处理冲突的也可以过。

       做法二:Trie字典树+dfs,可以找一些相关资料学习一下然后抄一份板。

           有哪里不会可以去问高翔!

     1 #include<cstdio>
     2 #include<cstring>
     3 int n,m;
     4 char s[1000010];
     5 struct Trie
     6 {
     7     int index;
     8     Trie *next[3];
     9     Trie()
    10     {
    11         index=-1;
    12         memset(next,0,sizeof(next));
    13     }
    14 };
    15 Trie *root=new Trie;
    16 void Trie_Insert(Trie *tr,int len)
    17 {
    18     if(s[len]!='')
    19     {
    20         if(tr->next[s[len]-'a']==0)
    21            tr->next[s[len]-'a']=new Trie;
    22         Trie_Insert(tr->next[s[len]-'a'],len+1);
    23     }
    24     else
    25       tr->index=1;
    26 }
    27 bool dfs(Trie *tr,int len,int f)
    28 {
    29     if(s[len]=='' )
    30     {
    31         if(f==0 && tr->index==1)
    32           return true;
    33         else
    34           return false;
    35     }
    36     if(tr->next[s[len]-'a']!=0)
    37     {
    38         if(dfs(tr->next[s[len]-'a'],len+1,f))
    39           return true;
    40     }
    41     if(f==1)
    42     {
    43         int i;
    44         for(i=0;i<=2;i++)
    45            if(i!=s[len]-'a' && tr->next[i]!=0)
    46              if(dfs(tr->next[i],len+1,0))
    47                return true;
    48     }
    49     return false;
    50 }
    51 int main()
    52 {
    53     int i,j,k;
    54     scanf("%d%d",&n,&m);
    55     for(i=1;i<=n;i++)
    56     {
    57         scanf("%s",s+1);
    58         Trie_Insert(root,1);
    59     }
    60     for(i=1;i<=m;i++)
    61     {
    62         scanf("%s",s+1);
    63         if(dfs(root,1,1))
    64           printf("YES
    ");
    65         else
    66           printf("NO
    ");
    67     }
    68 }
    高翔代码

    2.18

    Problem A Random Teams

    题意:n 个人组成 m支队,每队的任意两个人成为朋友,求最少的朋友对数和最多的朋友对数

    简析:最少,n个人平均分,最多,其它队都是1个人,一个队 n-(m-1)人

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<math.h>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 int main()
     8   { long long  i,j,k,m,n;
     9       long long max,min;
    10       scanf("%I64d%I64d",&n,&m);
    11       max=(n-m+1)*(n-m)/2;
    12       min=n%m*(n/m+1)*(n/m)/2+(m-n%m)*(n/m)*(n/m-1)/2;
    13       printf("%I64d %I64d
    ",min,max);
    14       return 0;
    15    } 
    code from ctr

    Problem B Table Decorations

    题意:r个红色的气球,g个绿色的气球,b个蓝色的气球,每三个气球(这三个气球的颜色不能都相同)装饰一张桌子,求能够装饰多少张桌子

    简析:假设r < b < g,那么 ans = min(r+b,(r+g+b)/3)

     1 #include<iostream>
     2 #include<algorithm>
     3 using namespace std;
     4 int main(){
     5     long long a,b,c,maxn,minn;
     6     cin>>a>>b>>c;
     7     maxn = max(max(a,b),c);
     8     minn = min(min(a,b),c);
     9     b = a+b+c-maxn-minn;
    10     if(maxn/2>=(minn+b)) cout<<minn+b<<endl;
    11     else cout<<(maxn+minn+b)/3<<endl;
    12     return 0;
    13 }
    code from wangzhimin

    2.19

    Problem A Dreamoon and WiFi

    题意:给s1,s2两个等长+-串,s2含有?(代表+-概率相等),问s1,s2+-个数相等的概率。

    简析:如果s2中+(或者-)的个数大于s1中+(或者-)的个数,那么答案显然是0,

       否则答案为从问号中选取+(或者-)的方案数乘上概率pow(0.5,问号个数)。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 using namespace std;
     6 char s1[11], s2[11];
     7 
     8 int main(void)
     9 {
    10     scanf("%s %s", s1, s2);
    11     int l = strlen(s1);
    12     int p1 = 0, m1 = 0, p2 = 0, m2 = 0;
    13     for(int i = 0; i < l; i++)
    14     {
    15         if(s1[i] == '+') p1++;
    16         else m1++;
    17         if(s2[i] == '+') p2++;
    18         else if(s2[i] == '-') m2++;
    19     }
    20     double ans = 0.0;
    21     if(p2 <= p1 && m2 <= m1)
    22     {
    23         double tmp = 1.0;
    24         for(int i = 0; i < p1 - p2; i++) tmp *= 1.0 * (l - p2 - m2 - i) / (i + 1);
    25         ans = tmp / pow(2, l - p2 - m2);
    26     }
    27     printf("%.9f
    ", ans);
    28     return 0;
    29 }
    参考代码

    Problem B Dreamoon and Sums

    题意:给a和b,求满足mod(x,b)不为0,且div(x,b)/mod(x,b)=k,k属于[1,a]的所有x之和。

    简析: 令 d = div(x, b), m = mod(x, b),

       因为div(x,b)/mod(x,b)=k, 所以d = mk,

       由带余除法,我们有x = db + m,

       即 x = mkb + m = (kb + 1) * m

       我们知道余数的范围是[1, b-1],

       那么对于一个固定的k,它对答案的贡献是

       那么我们要求的和式即为,我们可以O(a)求出它,

       当然也可以把它进一步化简为

     1 #include<stdio.h>
     2 #include<algorithm>
     3 using namespace std;
     4 typedef long long ll;
     5 const ll modulo = 1e9+7;
     6 int main(){
     7     ll sum = 0,a,b;
     8     scanf("%I64d%I64d",&a,&b);
     9     ll A = ((a+1)*a/2)%modulo*b%modulo;
    10     A  = (A + a)%modulo;
    11     ll B = b*(b-1)/2%modulo;
    12     printf("%I64d
    ",A*B%modulo);
    13     return 0;
    14 }
    code from wzm

    2.20

    Problem A Worms

    题意:给出 n个a[i],第一块的编号从 1到a[1],第二块的编号从 a[1]+1到 a[2],q个询问编号为 x 的在哪一块

    简析:记录下每个编号所在的块

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath>   
     5 #include<algorithm>  
     6 using namespace std;
     7 
     8 typedef long long LL;
     9 int vis[1000005];
    10 
    11 int main()
    12 {
    13     int n,m,i,j,a,s=0;
    14     scanf("%d",&n);
    15     for(i=1;i<=n;i++){
    16         scanf("%d",&a);
    17         for(j=0;j<a;j++){
    18             s++;
    19             vis[s]=i;
    20         }
    21     }
    22     
    23     scanf("%d",&m);
    24     while(m--){
    25         scanf("%d",&a);
    26         printf("%d
    ",vis[a]);
    27     }
    28     return 0;
    29 }
    参考代码

    Problem B Captain Marmot

    题意:给出 4n 个点,每一个点对应有位置坐标和旋转中心,求每四个点组成正方形需要旋转的次数

    简析:枚举每个点的旋转的情况

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath>   
     5 #include<algorithm>  
     6 using namespace std;
     7 
     8 typedef long long LL;
     9 LL d[10];
    10 
    11 struct node{
    12     int x,y;
    13 } p[10][10],center[10];
    14 
    15 LL dis(node a,node b){
    16     return(LL)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    17 }
    18 
    19 void check(){
    20     int ans=10005;
    21     for(int i=0;i<4;i++)
    22     {
    23         for(int j=0;j<4;j++)
    24         {
    25             for(int k=0;k<4;k++)
    26             {
    27                 for(int l=0;l<4;l++)
    28                 {
    29                     d[0]=dis(p[i][0],p[j][1]);
    30                     d[1]=dis(p[j][1],p[k][2]);
    31                     d[2]=dis(p[k][2],p[l][3]);
    32                     d[3]=dis(p[l][3],p[i][0]);
    33                     d[4]=dis(p[i][0],p[k][2]);
    34                     d[5]=dis(p[j][1],p[l][3]);
    35                     sort(d,d+6);
    36                     if(d[0]==0)
    37                         continue;
    38                     else
    39                         if(d[0]==d[1]&&d[1]==d[2]&&d[2]==d[3]&&d[0]*2==d[4]&&d[4]==d[5])
    40                     {
    41                         ans=min(ans,i+j+k+l);
    42                         
    43                     }
    44                 }
    45 
    46             }
    47         }
    48     }
    49     
    50     if(ans!=10005) printf("%d
    ",ans);
    51     else printf("-1
    ");
    52 }
    53 
    54 int main()
    55 {
    56     int n,j;
    57     scanf("%d",&n);
    58     while(n--){
    59         for(int i=0;i<4;i++)
    60         {
    61             cin>>p[0][i].x>>p[0][i].y;
    62             cin>>center[i].x>>center[i].y;
    63             int xx=p[0][i].x-center[i].x;
    64             int yy=p[0][i].y-center[i].y;
    65             p[1][i].x=center[i].x-yy;
    66             p[1][i].y=center[i].y+xx;
    67             p[2][i].x=center[i].x-xx;
    68             p[2][i].y=center[i].y-yy;
    69             p[3][i].x=center[i].x+yy;
    70             p[3][i].y=center[i].y-xx;
    71         }
    72         check();        
    73     }
    74 return 0;    
    75 }
    参考代码

    2.21

    Problem A Design Tutorial: Learn from Life

    题意:电梯限载k人,n个人中第i个人要去${f}_{i}$层,电梯从a到b的时间为|a - b|,

       求电梯送完所有人回来最小时间。

    简析:贪心的把人按从高到低的顺序塞入电梯,每次走到k个人中最高的地方再回来。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 using namespace std;
     4 int p[2222];
     5 bool cmp(int a,int b){
     6     return a>b;
     7 }
     8 int main(){
     9     int n,k;
    10     long long sum = 0;
    11     scanf("%d%d",&n,&k);
    12     for(int i = 1; i<=n; i++){
    13         scanf("%d",&p[i]);
    14     }
    15     sort(p+1,p+n+1,cmp);
    16     for(int i = 1; i<=n; i = i+k){
    17         sum += (p[i]-1)*2;
    18     }
    19     printf("%d
    ",sum);
    20     return 0;
    21 }
    code from wzm

    Problem B Design Tutorial: Make It Nondeterministic

    题意:n个人,每个人有两个ID,让每人选一个ID后,问构成的字典序能否与给定的排列一致。

    简析:根据给出的序列从小到大,我们贪心的让每个人尽可能选小的串,如果两串都小于前面就无解。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<string>
     4 using namespace std;
     5 const int N=1e5+1;
     6 string a[N],b[N];
     7 string c="";
     8 int p[N],n,i,t;
     9 int main(){
    10     cin>>n;
    11     for(i=0;i<n;++i)
    12         cin>>a[i]>>b[i];
    13     for(int i=0;i<n;++i)
    14         cin>>p[i];
    15     for(i=0;i<n;++i){
    16         t=--p[i];
    17         if(a[t]>b[t])  swap(a[t],b[t]);
    18         if(c<a[t]) c=a[t];
    19         else if(c<b[t]) c=b[t];
    20         else {cout<<"NO"<<endl;return 0;}
    21     }
    22     cout<<"YES"<<endl;
    23     return 0;
    24 }
    参考代码

    regular 数学专题

    2.15

    HDU 1130 How Many Trees? 题解 卡特兰数

    HDU 3625 Examining the Rooms 题解 斯特林数

    2.16

    POJ 1061 青蛙的约会 题解 扩展欧几里得

    HDU 4135 Co-prime 题解 容斥原理

    2.17

    HDU 2147 kiki's game 题解 巴什博弈

    POJ 1365 Prime Land 题解 素数分解

    2.18

    POJ 1850 Code 题解 组合数学

    HDU 4349 Xiao Ming's Hope 题解 Lucas定理(打表找规律?)

    2.19

    POJ 2409 Let it Bead 题解 Polya定理

    HDU 1695 GCD 题解 莫比乌斯反演

    2.20

    CodeForces 154B Colliders 题解 素数分解

    SGU 106 The equation 题解 扩展欧几里得

    2.21

    POJ 3252 Round Numbers 题解 组合数学

    HDU 1536 S-Nim 题解 博弈

  • 相关阅读:
    下拉选择框,允许手动输入和过滤
    MVC数据绑定
    一个页面多个ng-app注意事项
    modal 多层弹窗 Maximum call stack size exceeded 解决方法
    VS10x CodeMap 注册码(key):
    VS2015卸载再安装
    VS2015无法创建工程
    解决VS2015版本key required问题手动方案
    猪猪公寓—事后诸葛亮
    猪猪公寓——测试总结
  • 原文地址:https://www.cnblogs.com/chdacm/p/5190869.html
Copyright © 2011-2022 走看看