30 条题解

  • 95
    @ 2023-3-11 15:55:50
    #include<iostream>
    using namespace std;
    int main()
    {//阳光开朗大男孩把题解写出来了!写出来了!不用谢,点个赞就行!
        long long x; 
        cin>>x;
        long long n=2;
        for(int i=0;i<x;i++)
        { 
            n=2*n+2;
        } 
        cout<<n; 
        return 0;
    }
    
  • 49
    @ 2023-5-14 16:41:06

    数学解法秒杀,跟递归没什么关系 但是考虑到一部分人的需要,我给一下递归算法吧

    递归函数

    int f(int n){
        if(n<=2)return 0;
        return func((n-1)/2)+1;
    

    然后你可以用二分查找定位最大的n使得f(n)==x,记得nlong long类型

    那么,既然递归算法都想到了,尝试着使用更加简洁易懂的代码完成题目吧:

    对于一段长度为n的绳子,对它分割产生长度分别为a,b,c的三段,由题a,b,c≥1,不妨设a≤b≤c,则我们最终会保留长度为b的那一段

    对于长度为p的绳A与长度为p+1的绳B,对绳A的每一种分割方式 A={A[1],A[2],A[3]},其中A[1]≤A[2]≤A[3], 我们可以对绳B作如下分割:B={A[1],A[2],A[3]+1} 则此时以此为分割方式的A的最大分割次数f(A)=f(A[2])+1 B的最大分割次数f(B)=f(A[2])+1 =f(A) 此外我们有时还可以对绳B作一些无法对绳A作的分割f(B) 令F(p)={x|x=f(A)},F(p+1)={x|x=f(B)},则根据以上有

    F(p)⊆F(p+1)

    又因为f(p)为F(p)的最大元,f(p+1)为F(p+1)的最大元,有

    f(p)≤f(p+1)

    因此,为了产生最大化的分割次数,我们需要使每一次分割后留下的绳子长度最大化,即

    使b最大

    我们需要在保持a≤b≤c的前提下使得b取最大值 ∵a+b+c=n,a≥1,b≤c ∴b=(b+b)/2≤(b+c)/2=(n-a)/2≤(n-1)/2 其中第一个等号在b=c时取得,第二个在a=1时取得 总结一下,即

    b=[(n-1)/2]

    此时f(n)=f(b)+1=f([(n-1)/2])+1 用m=[(n-1)/2]替换,得

    f(2m+2)=f(m)+1

    f(2m+3)=f(m+1)+1

    则对f(r)=k-1,f(r+1)=f(s)=k,f(s+1)=k+1,有

    s=2r+2

    使f(n)=x的最大ng[x],则有

    g[x]=2·g[x-1]+2

    t≤2,我们知f(t)=0,同时f(3)=f(1)+1 =1使f(t)=0的最大t为2,即

    g[0]=2

    因此我们写下新的递归代码

    long long g(int n){
        if(n==0)return 2;
        return 2*g(n-1)+2;
    }
    

    整理递归代码,得到递推思想的简单代码

    int main(){
        long long x=2;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)x=2*++x;
        cout<<x;
        return 0;
    }
    

    但是这还不够!我们先前只得到了数列g的递推公式,还没有得到通项公式呢! 所以我们借助我们的数学功底,得到通项公式:

    g[x]=Σ(下标i=1,上标x+1)2^i

    再进行整理,得

    g[x]=2^(x+2)-2

    于是我们可以用以下的代码解决:

    #include<iostream>
    using namespace std;
    int main(){
        int x;
        cin>>x;
        cout<<(1<<x+2)-2;
        return 0;
    }
    

    理论上这段代码是正确的,但是实际上会数据溢出😕 所以会有两个WA(用long long类型也不行,是左移运算符的缺陷导致的)

    因此我们得到最终的代码:

    AC代码

    int main(){
        long long x=2;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)x=2*++x;
        cout<<x;
        return 0;
    }
    

    左移简便代码(非AC)

    #include<iostream>
    using namespace std;
    int main(){
        int x;
        cin>>x;
        cout<<(1<<x+2)-2;
        return 0;
    }
    

    制作不易,给个点赞吧

  • 17
    @ 2023-3-10 21:32:32

    P1006 【挑战题】分割

    题目描述

    有一段长度为正整数的绳子,将以下的操作持续到绳长变为2或更小:选择两个位置将绳子截成长度为正整数的三段,丢弃其中最长的一段和最短的一段。

    当对长度为n的绳子进行此操作时,令f(n)为该操作可进行的最多次数。

    给出正整数x,求使f(n)=x的最大整数n。


    逆向思考,他给次数?我们从二开始倒退!

    根据题意,为了让操作次数尽量多,每次分割绳子的时候,需要让被留下的那一段尽量长,那么:

    最短的那段长度一定是1,剩下两段一定是尽量平均分的,也就是说这两段相差不会超过1。

    比如,当前长度是8,那么分成1,3,4三段,此时剩下的3是最长的。

    按照此规则,假设某次分割后剩下的长度是n,则本次分割出的三段分别是1,n,n+1,总和2n+2。

    因此,从n=2开始,每次根据当前的n,求出分割前的长度2n+2,重复x次即可求出

    (这里引用一下@hetaowjl(SU)的题解,在此表示感谢)


    参考代码:

    #include <iostream>//hetao3097453
    using namespace std;
    int main()
    {
        int n;
        cin >> n;
        int x = 2;
        for(int i = 1;i <= n;i++)
        {
            x = 2 * x + 2;
        }
        cout << x << endl;
        return 0;
    }
    

    -然鹅:

    image

    …………………………………………………………

    所以,用 long long 一定不会错

    #include <iostream>//hetao3097453
    using namespace std;
    int main()
    {
        long long n;
        cin >> n;
        long long x = 2;
        for(int i = 1;i <= n;i++)
        {
            x = 2 * x + 2;
        }
        cout << x << endl;
        return 0;
    }
    

    hetao3097453(blililil @ 一钩出站)

    2023年3月10日

  • 11
    @ 2023-9-9 17:31:22

    这构思玩意能AC??!!

    #include<iostream>
    using namespace std;
    #define POPOPOPOPOPOPOPOPOPOPOPOPOOPOPLOL return
    #define QWERTYUIO_____________________________ for
    #define ______________________________________________ int
    #define IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIllllllllllllllllllllllllllllllllllIIIIIIIIIIIIIIIIIIIIIIIIII long long
    ______________________________________________ main()
    
    {
        IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIllllllllllllllllllllllllllllllllllIIIIIIIIIIIIIIIIIIIIIIIIII x; 
        cin>>x;
        IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIllllllllllllllllllllllllllllllllllIIIIIIIIIIIIIIIIIIIIIIIIII n=2;
        QWERTYUIO_____________________________(______________________________________________ i=0;i<x;i++)
        { 
            n=2*n+2;
        } 
        cout<<n; 
        POPOPOPOPOPOPOPOPOPOPOPOPOOPOPLOL 0;
    }
    
  • 4
    @ 2024-1-6 17:08:06
    #include <iostream>
    #include <bits/stdc++.h>
    #include <stdio.h>
    #include <iomanip>
    using namespace std;
    int main(){
        long long x=2;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)x=2*++x;
        cout<<x;
        return 0;
    }
    
    • 4
      @ 2023-6-25 19:39:55

      这一题最重要的就是找到规律(就是规律有点难找……)

      #include <bits/stdc++.h>
      using namespace std;
      long long f(long long x)       //不带把数据开得这么大的……
      {
          if (x == 1)
              return 6;              //递归边界
          return 2 * f(x - 1) + 2;   //规律(这一次的结果=2×上一次的结果+2)
      }
      int main()
      {
          int x;
          cin >> x;
          cout << f(x);              //我个人还是比较习惯用递归
          return 0;
      }
      

      不习惯用递归的↓

      #include <bits/stdc++.h>
      using namespace std;
      int main()
      {
          long long x, ans=2;
          cin >> x;
          for (int i = 1; i <= x; i++) //和递归函数一个作用
              ans = 2 * ans + 2;
          cout << ans;
          return 0;
      }
      

      两种代码都试过了,皆AC

    • 4
      @ 2023-2-28 15:20:20
      提示1
              本题不需要使用递归。

      提示2
              需要逆向思考这个问题(从2开始不断把绳子变长)。

      提示3
              每次舍掉的最短的那一段,长度一定是1。

      完整思路
              题目求的是最大的n,那么为了让n尽量大,应该让绳子被操作x次后,最终得到2(而不是得到1)。

              反过来考虑,也就是从2开始,复原x次,最终得到n。

              根据题意,为了让操作次数尽量多,每次分割绳子的时候,需要让被留下的那一段尽量长,那么:

                  1. 最短的那段长度一定是1。

                  2. 剩下两段一定是尽量平均分的,也就是说这两段相差不会超过1。

              比如,当前长度是8,那么分成1,3,4三段,此时剩下的3是最长的。

              按照此规则,假设某次分割后剩下的长度是n,则本次分割出的三段分别是1,n,n+1,总和2n+2。

              因此,从n=2开始,每次根据当前的n,求出分割前的长度2n+2,重复x次即可求出答案。

      • 3
        @ 2024-4-13 15:21:20
        #include <iostream>
        using namespace std;
        int main()
        {
            long long x;
            cin >> x;
            long long n=2;
            for (int i=0; i<x; i++)
            {
                n=2*n+2;
            }
            cout << n;
            return 0;
        }//先赞后看养成好习惯
        
        • 2
          @ 2023-10-13 22:12:07

          C2每课一题解(第二课 第三题)!!!

          此题简单-中等,用递归就可以推出,但其实可以不用递归,用正常做法就好了。

          话不多说,上代码!

          AC Code

          #include<iostream>
          using namespace std;
          int main()
          {
              long long x=2;
              int n;
              cin>>n;
              for(int i=1;i<=n;i++)
              {
                  x=2*(x+1);
              }
              cout<<x;
              return 0;
          }
          
          • 0
            @ 2023-10-14 19:27:32

            讲一下大致思路:首先,函数定义一定用long long ,int只能达到2的31次方,而本题最大可将近2的42次方;其次,找到相邻两项之间的关系:当x为1时,结果为6,当x为2时,结果为14......大家可能看出来了,第2项为前1项*2+2;原理:我们最好能够将最短的绳子为1,最长的绳子和第二长的绳子相等(或相差1),注意到,6=1+2+3,14=1+6+7,30=1+14+15......于是就有了下面的函数主体代码:

            long long f(int n)
            {
                if(n==1)
                {
                    return 6;
                }
                return 2+2*f(n-1);
            }
            

            【本人B站:冷焰LY111(不是编程,是游戏UP,感兴趣的可以去看)】

            • 0
              @ 2023-10-14 18:51:48

              绝对不短小精悍

              #include<bits/stdc++.h>
              int main()
              {
                  long long x; 
                  std :: cin >> x; 
                  long long n;
                  n = 2;
                  int i;
                  i = 1;
                  while(i <= x)
                  {
                      n = n + n;
                      n = n + 2;
                      i = i + 1;
                  }
                  std :: cout << n << std :: endl; 
                  return std :: string :: npos + 1;
              }
              
              • 0
                @ 2023-7-25 15:40:56

                -题目回顾-

                有一段长度为正整数的绳子,将以下的操作持续到绳长变为2或更小:选择两个位置将绳子截成长度为正整数的三段,丢弃其中最长的一段和最短的一段。

                当对长度为n的绳子进行此操作时,令f(n)为该操作可进行的最多次数。

                给出正整数x,求使f(n)=x的最大整数n。


                -分析-

                最小一段最小为二,我们就取二;而剩下的就是留下的一段*2,即n * 2.根据这个,我们就可以退出来通项公式:n = n * 2 + 2;


                代码如下:

                #include <bits/stdc++.h>//by AGOMG
                using namespace std;
                long n = 2, x;
                int main()
                {
                    cin >> x;
                    for(int i = 1; i <= x; i++)
                        n = n * 2 + 2;
                    cout << n;
                    return 0;
                }
                
                • 0
                  @ 2023-3-19 15:46:12
                  #include <iostream>
                  using namespace std;
                  int main()
                  {
                      long long n;//记得用long long!
                      cin >> n;
                      long long x = 2;
                      for(int i = 1;i <= n;i++)
                      {
                          x = 2 * x + 2;
                      }
                      cout << x << endl;
                      return 0;
                  }
                  
                  • 0
                    @ 2023-3-11 16:29:02
                    #include<iostream>
                    using namespace std;
                    int main()
                    {
                        long long n; 
                        cin>>n;
                        long long x=2;
                        for(int i=0;i<n;i++)
                        { 
                            x=2*x+2;
                        } 
                        cout<<x; 
                        return 0;
                    }
                    
                    
                    • 0
                      @ 2023-3-11 6:57:52
                      #include<bits/stdc++.h>
                      using namespace std;
                      int main(){
                          long long x; cin >> x; long long n = 2;
                          for(int i = 1;i <= x;i++) n = 2 * n + 2;
                          cout << n << endl; return 0;
                      }
                      

                      思路参考:@hetao3097453 这是一段比较“凝练”的代码

                    • -1
                      @ 2024-5-19 16:41:30
                      #include <bits/stdc++.h>
                      using namespace std;
                      long long f(long long x){
                          if (x == 1)
                              return 6;//递归边界
                          return 2*f(x-1)+2;//继续调用函数
                      }
                      int main(){
                          long long n;
                          cin >> n;
                          cout << f(n);
                          return 0;
                      }
                      
                      制作不易,只求点赞(^__^)
                      
                      • -1
                        @ 2024-3-2 19:22:30

                        #include <bits/stdc++.h> using namespace std;

                        long long n,a[42]; //列表储存每一个x的对应值 int main() { a[1]=6; // a[2]=14; //初始值 cin>>n; for (int i=3;i<=n;i++) { a[i]=a[i-1]*2+2; //找规律计算 } cout <<a[n]; //输出所需 return 0; }

                        AC码子 不需要用递归 和递归一个性质

                        • -1
                          @ 2024-3-1 19:28:27
                          #include<iostream>
                          using namespace std;
                          int main()
                          {//题解写出来了!写出来了!不用谢,点个赞就行!
                              long long x; 
                              cin>>x;
                              long long n=2;
                              for(int i=0;i<x;i++)
                              { 
                                  n=2*n+2;
                              } 
                              cout<<n; 
                              return 0;
                          }
                          
                          • -1
                            @ 2023-6-24 21:02:38

                            其实就是找到规律

                            #include <bits/stdc++.h> using namespace std;

                            long long n;

                            long long f(int a) { if(a == 0) { return 2; } return 2 * f(a-1) + 2; }

                            int main() { cin >> n; cout << f(n); return 0; }

                            • -1
                              @ 2023-5-20 20:32:24

                              #include<iostream> using namespace std; int main() { long long n; cin>>n; long long x=2; for(int i=0;i<n;i++) { x=2*x+2; } cout<<x; return 0; }

                              信息

                              ID
                              10
                              时间
                              1000ms
                              内存
                              256MiB
                              难度
                              5
                              标签
                              递交数
                              4776
                              已通过
                              1729
                              上传者