zoukankan      html  css  js  c++  java
  • 寒假练习题解 第六周 2.22-2.28

    每日一练

    2.22

    Problem A MUH and Important Things

    题意:给出一列数 a[i],输出三种不同的升序排列的方式

    简析:记录下值相等的位置,如果<=1,就不能构成,然后每次输出,交换一个

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<queue> 
     9 #include<algorithm>  
    10 #define mod=1e9+7;
    11 using namespace std;
    12 
    13 typedef long long LL;
    14 const int maxn=2000+5;
    15 int b[maxn];
    16 
    17 struct node{
    18     int h;
    19     int pos;    
    20 } a[maxn];
    21 
    22 int cmp(node n1,node n2){
    23     if(n1.h!=n2.h) return n1.h<n2.h;
    24     return n1.pos<n2.pos;
    25 }
    26 
    27 int main(){
    28     int n,i,j,cnt;
    29     cin>>n;
    30     for(i=1;i<=n;i++){
    31         cin>>a[i].h;
    32         a[i].pos=i;
    33     }
    34     
    35     sort(a+1,a+n+1,cmp);
    36     cnt=0;
    37     
    38     for(i=2;i<=n;i++){
    39         if(a[i].h==a[i-1].h){
    40             b[cnt++]=i-1;
    41         }
    42     }
    43     if(cnt<=1) printf("NO
    ");
    44     else{
    45         printf("YES
    ");
    46         for(i=1;i<n;i++)
    47         printf("%d ",a[i].pos);
    48         printf("%d
    ",a[i].pos);
    49         
    50         swap(a[b[0]],a[b[0]+1]);
    51         
    52         for(i=1;i<n;i++)
    53         printf("%d ",a[i].pos);
    54         printf("%d
    ",a[i].pos);
    55         
    56     //    swap(a[b[0]],a[b[0]+1]);
    57         swap(a[b[1]],a[b[1]+1]);
    58         
    59         for(i=1;i<n;i++)
    60         printf("%d ",a[i].pos);
    61         printf("%d
    ",a[i].pos);        
    62     }
    63     return 0;
    64 }
    参考代码

    Problem B MUH and House of Cards

    题意:给出 n 张牌,求恰好可以用这n张牌搭成多少个不同高度的房子

    简析:可以算出高度 为 n 的房子至少需要的牌为 n*2 +(n-1) + (n-1)*2 +(n-2) + ...+1*2 +0

    化简就是 (3n*n+n)/2,又因为搭成一个房间需要3张牌,所以最后剩下的判断是否能够整除3,再搭在第一层就可以了

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<queue> 
     9 #include<algorithm>  
    10 #define mod=1e9+7;
    11 using namespace std;
    12 
    13 typedef long long LL;
    14 LL n;
    15 LL ans,tmp,row,sum=0;
    16 
    17 int main(){
    18     cin>>n;
    19     for(LL i=1;(tmp=(3*i+1)*i/2)<=n;i++){
    20         
    21         if((n-tmp)%3==0)
    22         ans++;
    23     }
    24     cout<<ans<<"
    ";
    25     return 0;    
    26 }
    参考代码

    2.23

    Problem A Chat Online

    题意:已知区间集$left { left [ a_i, b_i ight ] ight }$和$left { left [ c_i+t, d_i+t ight ] ight }$,求t使交最大。

    简析:暴力即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int main()
     6 {    
     7     int a[60],b[60],c[60],d[60],vis[1005];
     8     int p,q,l,r;
     9     memset(vis,0,sizeof(vis));
    10     scanf("%d%d%d%d",&p,&q,&l,&r);
    11     for(int i=1;i<=p;i++){
    12         scanf("%d%d",&a[i],&b[i]);
    13         for(int j=a[i];j<=b[i];j++) vis[j]=1;
    14     }
    15     for(int i=1;i<=q;i++) scanf("%d%d",&c[i],&d[i]);
    16     int ans=0;
    17     for(int i=l;i<=r;i++){
    18         int flag=0;
    19         for(int j=1;j<=q;j++)
    20         {
    21             for(int k=c[j]+i;k<=d[j]+i&&k<=1000;k++)
    22                 if(vis[k]==1){
    23                     flag=1; break;
    24                 }
    25             if(flag==1){
    26                 ans++;
    27                 break;
    28             }
    29         }
    30     }
    31     printf("%d
    ",ans);
    32     
    33     return 0;
    34 }
    code from niu

    Problem B 24 Game

    题意:用1到n的数算24点。(没有除)

    简析:显然1,2,3,4就可以构造解了,2,3,4,5也可以,那么n分奇偶,构造1来抵消就阔以拉!

    备注:这个题对你们来说是不是太简单了!去年多校联合训练也有一个24点的构造题哦,来挑战一下吧!

    #include <iostream>
    #include <cstdio>
    #include <climits>
    using namespace std;
    
    int main()
    {
        int n;
        while(scanf("%d", &n) != EOF) {
            if(n <= 3) {
                printf("NO
    ");
            } else {
                printf("YES
    ");
                if(n % 2 == 0) {
                printf("1 * 2 = 2
    2 * 3 = 6
    6 * 4 = 24
    ");
                for(int i = 6; i <= n; i += 2) {
                    printf("%d - %d = 1
    ", i, i - 1);
                    printf("1 * 24 = 24
    ");
                }
            } else {
                printf("4 * 5 = 20
    2 + 20 = 22
    3 - 1 = 2
    2 + 22 = 24
    ");
                for(int i = 7; i <= n; i += 2) {
                    printf("%d - %d = 1
    ", i, i - 1);
                    printf("1 * 24 = 24
    ");
                }
            }
            }
    
        }
        return 0;
    }
    code from Kaen

    2.24

    Problem A Fedor and New Game

    题意:从 m 个数中找出和 x 的二进制位不同的位 <= k 的数的个数

    简析:每个算一下

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<set>
     9 #include<queue> 
    10 #include<algorithm>  
    11 #define mod=1e9+7;
    12 using namespace std;
    13 
    14 typedef long long LL;
    15 const int maxn=1000+5;
    16 int a[maxn];
    17 
    18 int main(){
    19     int n,m,k,i,j,ans=0;
    20     cin>>n>>m>>k;
    21     for(i=0;i<=m;i++) {
    22         cin>>a[i];
    23     }
    24     
    25     for(i=0;i<m;i++){
    26         ans+= __builtin_popcount(a[i]^a[m])<=k;
    27     }
    28     cout<<ans<<"
    ";
    29     return 0;
    30 }
    参考代码

    Problem B George and Job

    题意:从 n 个数中选出k 个长度为 m 的不相交的区间,求最大的和

    简析:dp[i][j] 表示前 i 个数选出 j 个区间的最大值

    dp[i][j] = max(dp[i-1][j],dp[i-m][j-1] + sum[i]-sum[i-m]) (sum[i] 为前i项和)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 typedef long long LL;
     8 LL dp[5005][5005];
     9 LL num[5005];
    10 int n,m,k;
    11 
    12 int main(){
    13     while(scanf("%d %d %d",&n,&m,&k) != EOF){
    14         memset(dp,0,sizeof(dp));
    15         num[0] = 0;
    16         for(int i = 1;i <= n;i++){
    17             int x;
    18             scanf("%d",&x);
    19             num[i] = num[i-1] + x;
    20         }
    21         
    22     //    for(int i = 1;i <= n;i++)
    23     //    printf("num[%d] = %d
    ",i,num[i]);
    24         
    25         for(int i = 1;i <= n;i++){
    26             for(int j = 1;j <= k;j++){
    27                 if(i-m < 0) continue;
    28                 dp[i][j] = max(dp[i-1][j],dp[i-m][j-1] + num[i] - num[i-m]);
    29             //    printf("dp[%d][%d] = %I64d
    ",i,j,dp[i][j]);
    30             }
    31         }
    32         printf("%I64d
    ",dp[n][k]);
    33     }
    34     return 0;
    35 }
    参考代码

    2.25

    Problem A Sort the Array

    题意:问能否翻转一段使序列递增。

    简析:先排序后两序列比较,找出第一个不一样的位置与最后一个不一样的位置,

       判断将这一段翻转后是否递增,是则为答案,否则无解。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int n,s,a[100001],b[100001],ans[100001];
     5 int main()
     6 {
     7     scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];sort(b+1,b+n+1);
     8     for(int i=1;i<=n;i++)if(a[i]!=b[i])ans[++s]=i;
     9     for(int i=ans[1];i<=ans[s];i++)if(a[ans[1]+ans[s]-i]!=b[i]){printf("no
    ");return 0;}
    10     if(!s)ans[0]=ans[1]=1;printf("yes
    %d %d
    ",ans[1],ans[s]);return 0;
    11 }
    不参考代码

     

    Problem B Predict Outcome of the Game

    题意:3队打n次比赛已经打k场,设三队胜数分别为${x}_{1}$,${x}_{2}$,${x}_{3}$,已知${d}_{1} = |{x}_{1}-{x}_{2}|$,${d}_{2} = |{x}_{2}-{x}_{3}|$.

       问是否存在三队胜数相同的情况。

    简析:首先如果n不是3的倍数必然无解,

       讨论${x}_{1}$,${x}_{2}$,${x}_{3}$的大小拆绝对值,得到两个方程,

       又有${x}_{1}+{x}_{2}+{x}_{3}=k$,联立三个方程就能解得${x}_{1}$,${x}_{2}$,${x}_{3}$的值,

       如果三者均小于等于$frac{n}{3}$则yes,否则为no。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 #define LL long long
     6 LL t,n,k,d1,d2;
     7 bool _(LL a,LL b){return (a/3>=b && a/3*3==a && a<=n);}
     8 bool x()
     9 {
    10     if(n%3)return false;
    11     if(_(n-k+d1+d2*2,d1+d2))return true;
    12     if(_(n-k+d2+d1*2,d1+d2))return true;
    13     if(_(n-k+d1+d2,max(d1,d2)))return true;
    14     if(_(n-k-min(d1,d2)+max(d1,d2)*2,max(d1,d2)))return true;
    15     return false;
    16 }
    17 int main(){scanf("%I64d",&t);for(LL i=0;i<t;i++)cin>>n>>k>>d1>>d2,printf("%s
    ",x()?"yes":"no");return 0;}
    不参考代码

    2.26

    Problem A Jzzhu and Sequences

    题意:f[i] = f[i-1] + f[i+1] ,求f[i] mod 1e9+7

    简析:f[i+1] = f[i] - f[i-1]

    所以求出

    f[1] = x;

    f[2] = y;

    f[3] = y-x;

    f[4] = -x;

    f[5] = -y;

    f[6] = -y+x;

    f[7] = x.....以6为循环

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<set>
     9 #include<queue> 
    10 #include<algorithm>  
    11 using namespace std;
    12 
    13 typedef long long LL;
    14 const int INF = (1<<30)-1;
    15 const int mod=1000000007;
    16 const int maxn=100005;
    17 
    18 LL a[15];
    19 
    20 int main(){
    21     LL x,y,n;
    22     cin>>x>>y;
    23     cin>>n;
    24     a[1]=(x+mod)%mod;
    25     a[2]=(y+mod)%mod;
    26     a[3]=(y-x+2*mod)%mod;
    27     a[4]=(-x+mod)%mod;
    28     a[5]=(-y+mod)%mod;
    29     a[0]=(-y+x+2*mod)%mod;
    30     cout<<a[n%6]<<"
    ";
    31     return 0;
    32 }
    View Code

    Problem B Jzzhu and Chocolate

    题意:一块 n*m 的巧克力,切k刀,求最小的块的最大的面积

    简析:最多能切n+m-2刀,如果 k > n+m-2,就不行

    假设n > m

    如果 k <= n-1,那么就只在竖直或者水平方向切割,取较大的

    如果 k > n-1,就先在水平或者竖直方向切,再在没有切完的方向切完剩下的,取较大的

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<set>
     9 #include<queue> 
    10 #include<algorithm>  
    11 using namespace std;
    12 
    13 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
    14 
    15 typedef long long LL;
    16 const int INF = (1<<30)-1;
    17 const int mod=1000000007;
    18 const int maxn=1000005;
    19 
    20 int main(){
    21     LL n,m,k;
    22     cin>>n>>m>>k;
    23     if(m>n) swap(m,n);
    24     
    25     LL ans=-1;
    26     if(k>(n+m-2)) {
    27         printf("-1
    ");
    28         return 0;
    29     }
    30     
    31     LL res,l,r;
    32     if(k<(n-1)){
    33         LL a=n/(k+1);
    34         LL b=m/(k+1);
    35     //    printf("a=%d
    ",a);
    36     //    printf("b=%d
    ",b);
    37         ans=max(a*m,b*n);
    38         
    39         
    40     }
    41     else{
    42         LL a=k-(n-1);//��m��a�� 
    43         LL b=k-(m-1);//������n��b��
    44         
    45         ans=max(m/(a+1),n/(b+1)); 
    46         
    47         
    48         
    49     }
    50     printf("%I64d
    ",ans);
    51 }
    View Code

    2.27

    Problem A Suffix Structures

    题意:给两个串,问能否由一个串经过删字母和调换字母顺序得到另一个串。

    简析:先检查能否只用删除,然后统计每个字母数对比即可。

     1 #include <iostream>
     2 #include <vector>
     3 using namespace std;
     4 
     5 vector<int> countChar(string s) {
     6     vector<int> res (256);
     7     for (int i = 0; i < (int) s.size(); ++i)
     8         ++res[(int) s[i]];
     9     return res;
    10 }
    11 
    12 bool isSubsequence(string p, string t) {
    13     for (int i = 0, j = 0; i < (int) p.size(); ++i) {
    14         while (j < (int) t.size() && p[i] != t[j])
    15             ++j;
    16         if (j == (int) t.size())
    17             return false;
    18         ++j;
    19     }
    20     return true;
    21 }
    22 
    23 int main() {
    24     string s, t;
    25     cin >> s >> t;
    26     vector<int> cs = countChar(s);
    27     vector<int> ct = countChar(t);
    28     if (isSubsequence(t, s)) {
    29         cout << "automaton";
    30     } else if (cs == ct) {
    31         cout << "array";
    32     } else {
    33         bool both = true;
    34         for (int i = 0; i < (int) cs.size(); ++i)
    35             both &= cs[i] >= ct[i];
    36         cout << (both ? "both" : "need tree");
    37     }
    38     return 0;
    39 }
    View Code

    Problem B Painting Fence

    题意:给一排木板高度,可以横向或者纵向刷油漆,问最少要刷几次。

    简析:考虑到最优解时所有横刷的下方必然也是横刷,

       那么我们刷[l,r]这个范围内木板的数目完全由横刷的高度h决定。

       横刷过后可能使得上方的木板不连通,但是上方的木板可以归结为子问题,因此可以递归来解决。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 using namespace std;
     5 int a[5555];
     6 
     7 int solve(int l, int r, int h)
     8 {
     9     int m = a[l], x = l - 1, tmp = 0;
    10     for(int i = l; i <= r; i++) m = min(m, a[i]);
    11     for(int i = l; i <= r; i++)
    12     {
    13         if(a[i] == m)
    14         {
    15             if(x < i - 1) tmp += solve(x + 1, i - 1, m);
    16             x = i;
    17         }
    18     }
    19     if(x != r) tmp += solve(x + 1, r, m);
    20     return min(r - l + 1, tmp + m - h);
    21 }
    22 
    23 int main(void)
    24 {
    25     int n;
    26     scanf("%d", &n);
    27     for(int i = 1; i <= n; i++) scanf("%d", a + i);
    28     printf("%d
    ", solve(1, n, 0));
    29     return 0;
    30 }
    View Code

    2.28

    Problem A DZY Loves Strings

    题意:给出一个字符串和 26 个字母的权值,插入k个字母,求字符串的最大权值

    简析:插入k个权值最大的字母

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<set>
     9 #include<queue> 
    10 #include<algorithm>  
    11 using namespace std;
    12 
    13 typedef long long LL;
    14 const int INF = (1<<30)-1;
    15 const int mod=1000000007;
    16 const int maxn=100005;
    17 char s[1005];
    18 int a[30];
    19 
    20 int main(){
    21     int k;
    22     cin>>(s+1);
    23     cin>>k;
    24     int maxx=-1;
    25     for(int i=0;i<26;i++){
    26         cin>>a[i];
    27         maxx=max(maxx,a[i]);
    28     }
    29     int len=strlen(s+1);
    30     int ans=0;
    31     for(int i=1;i<=len;i++ ){
    32         ans+=i*a[s[i]-'a'];
    33     }
    34     
    35     for(int i=len+1;i<len+1+k;i++)
    36     ans+=i*maxx;
    37     printf("%d
    ",ans);
    38     return 0;
    39 }
    View Code

    Problem B DZY Loves Sequences

    题意:给出 n 个数,可以将其中的一个数修改成任意的值,求最长严格递增序列的长度

    简析:预先处理出 l[i] 为 a[i] 作为最大值最多能够向左延伸的长度,r[i] 为a[i] 作为最小值最多能够向右延伸的长度

    如果 a[i-1] < a[i+1]-1 更新答案 ans = max(ans,l[i-1]+r[i+1]+1) (将这两段拼在一起)

    如果不满足 更新答案ans = max(ans,max(l[i-1],r[i+1])+1) (取较长的一段)

     1 #include<iostream>  
     2 #include<cstdio>  
     3 #include<cstring> 
     4 #include <cmath> 
     5 #include<stack>
     6 #include<vector>
     7 #include<map> 
     8 #include<set>
     9 #include<queue> 
    10 #include<algorithm>  
    11 using namespace std;
    12 
    13 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
    14 
    15 typedef long long LL;
    16 const int INF = (1<<30)-1;
    17 const int mod=1000000007;
    18 const int maxn=1000005;
    19 
    20 int a[maxn],l[maxn],r[maxn];
    21 
    22 int main(){
    23     int n;
    24     scanf("%d",&n);
    25     for(int i=1;i<=n;i++) {
    26         scanf("%d",&a[i]);
    27         l[i]=r[i]=1;
    28     }
    29     
    30     l[0]=0;r[0]=0;
    31     
    32     for(int i=2;i<=n;i++){
    33         if(a[i]>a[i-1]) l[i]+=l[i-1];
    34     }
    35     for(int i=n-1;i>=1;i--){
    36         if(a[i+1]>a[i]) r[i]+=r[i+1];
    37     }
    38     
    39     int ans=0;
    40     a[0]=INF;
    41     a[n+1]=-INF;
    42     l[0]=0;
    43     r[n+1]=0;
    44     for(int i=1;i<=n;i++){
    45         if(a[i-1]<a[i+1]-1) ans=max(ans,l[i-1]+r[i+1]+1);
    46         else ans=max(ans,max(l[i-1],r[i+1])+1);
    47         
    48     //    printf("ans=%d
    ",ans);        
    49     }
    50     printf("%d
    ",ans);
    51     return 0;
    52 }
    View Code

    bonus 字符串专题

    2.22

    你需要一个KMP的模板。

    HDU 1711 Number Sequence 题解

    HDU 1686 Oulipo 题解

    2.23

    如果理解了Next数组,循环节的性质也不难理解。

    HDU 3746 Cyclic Nacklace 题解

    HDU 1358 Period 题解

    2.24

    POJ 2752 Seek the Name, Seek the Fame 题解

    HDU 2594 Simpsons’ Hidden Talents 题解

    2.25

    HDU 3336 Count the string 题解

    HDU 4300 Clairewd’s message 题解 也可以学习下扩展kmp的做法

    2.26

    HDU 2609 How many 题解

    HDU 3374 String Problem 题解

    2.27

    HDU 3613 Best Reward 题解

    ↓↓↓↓手滑挂错题 要用Trie

    POJ 3376 Finding Palindromes 题解

    2.28

    POJ 3974 Palindrome 题解

    HDU 4513 吉哥系列故事――完美队形II 题解

  • 相关阅读:
    socket架构
    异常处理
    类的装饰器
    with&as上下文管理协议
    软件开发规范
    面向对象-描述符
    面向对象-迭代器
    面向对象编程多种特性
    体验Visual Studio 2015 之 MVC
    MVC 好记星不如烂笔头之 ---> 全局异常捕获以及ACTION捕获
  • 原文地址:https://www.cnblogs.com/chdacm/p/5208119.html
Copyright © 2011-2022 走看看