A - Link/Cut Tree, C - Maximum Product, E - Combination output. Question description + reference code + code explanation - the third experiment of the algorithm course of the School of Software Engineering, Sun Yat-sen University. Must-do questions

Now we are in a confusing { } intermediate state, sometimes with line breaks and sometimes without line breaks...

Line breaks do look cleaner. But it looks more complete without line breaks. No wonder those who learn C are arguing about this issue.

Doing the required questions first means grasping the main contradiction

 A - Link/Cut Tree

Question description

Reference Code

#include<iostream>
#include<cmath>
using namespace std;
#define ll long long
ll getAns(ll k,ll p){
    ll ans=1;
    for(int i=1;i<=p;i++)
        ans*=k;
    return ans;
}
int main()
{
    ll l,r,k,p;
    while(cin>>l>>r>>k)
    {
        p=0;
        bool legal=false;
        while(true){
            if(pow(k,p)>r)
                break;
            if( pow(k,p)>=l && pow(k,p)<=r ){
                cout<<getAns(k,p)<<" ";
                legal=true;
            }
            p++;
        }
        if(!legal)
            cout<<-1<<endl;
    }
}

Code explanation

The beauty

I think the first clever point is #define ll long long. After all, long long is too long to write.

The second one looks stupid, but in fact the clever thing is to use a separate function to calculate the ans value.

Two easy pitfalls

1. You cannot directly output the result of pow, because it will be expressed in scientific notation.

cout<<pow(k,p)<<" ";

 2. You cannot multiply first and then look at the symbol, which does not meet the conditions. ans *= k also exceeds long long!

C - Maximum Product

Question description

Reference Code 

#include<iostream>
#include<cmath>
using namespace std;
#define ll long long

int main(){
    int n;
    int ncase=0;
    while(cin>>n){
        ll ans=0;
        ll num[100];
        for(int i=0;i<n;i++){
            cin>>num[i];
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;i+j<n;j++){
                ll tmp=1;
                for(int k=0;k<=j;k++)
                    tmp*=num[i+k];
                if(tmp>ans)
                    ans=tmp;
            }
        }
        if(ans<0)
            ans=0;
        printf("Case #%d: The maximum product is %lld.\n\n",++ncase,ans);
    }
}

Code explanation

The core are two for loops that traverse possible intervals.

for(int j=0;i+j<n;j++) is quite good, especially i+j<n, which ensures that j is after i and everything can be traversed.

Another wonderful thing is that if(ans<0) ans=0; directly solves all possible negative value situations at the end, without modifying the intermediate algorithm to add some judgments.

E - combined output

Question description

Reference Code

#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
using namespace std;
bool cmp(vector<int> a,vector<int> b){
  for(int i=0;i<a.size();i++)
  {
    if(a[i]!=b[i])// 这一步不可少
      return a[i]<b[i];
  }
}
int main(){
  int n,r;
  cin>>n>>r;
  vector<vector<int> > res;
  for(int i=0;i<(1<<n);i++){
    int cnt=0;
    for(int j=0;j<=n;j++){
      if(i&(1<<j)) {
        cnt++;
        cout << "i:" << i << endl;
        cout << "1<<j:" << (1 << j) << endl;
        cout<<"cnt:"<<cnt<<endl;
      }
    }
    if(cnt==r){
      vector<int> tmp;
      for(int j=0;j<=n;j++){
        if(i&(1<<j)){
          tmp.push_back(j+1);
        }
      }
      res.push_back(tmp);
    }
  }
  sort(res.begin(),res.end(),cmp);
  for(vector<int> a : res){
    for(int b : a){
      cout<<setw(3)<<b;
    }
    cout<<endl;
  }
}

Code explanation

This is really a clever application of bitwise operations.

Let's say the input is 5 3.

To choose 3 means to choose three different numbers among five numbers. In the binary system, there must be three ones among the five digits.

Traversing 2^n, for a specific i, such as 7, it is 01011. At this time, j is traversed from 0 to n-1, which means converting i into binary and scanning each bit. If the bit is 1, let cnt+1.

If cnt=r, it means that the number corresponding to i is exactly the selected r number of digits.

At this time, put the answer into a temporary array, and tmp.push_back(j+1) changes the index from 0 to 1.

There will be C(n,r) answers in the end.

i&(1<<j)

i&(1<<j) is a bit operation that checks whether bit of an integer i is 1. This kind of operation is common in algorithms related to combination, subset generation, or other bit operations. j

We use the bitwise operator & (AND operation) to perform this check. In this operation, we shift the number 1 to the left by j places, thereby creating a 1 that only has j Number (other bits are all 0). We then use & to compare this number with i and if the result is not 0, it means i's The a>j bit is 1, otherwise the bit is 0.

Let's illustrate with some examples:

  1. Check the th digit of the number i = 5 (counting from 0, the second digit): 1

    • First, we know that 5 is represented in binary as 101.
    • Using the operation1<<1, we shift the number 1 to the left by one position to get 10, that is, < a i=4>. 2
    • Currently, I am the commander 5 (immediately 101) given 2 (immediately 010) Progress & Calculation, Gain 0. This meaning number 5 number 1 rank 0.
  2. Check the th digit of the number i = 5 (counting from 0, the third digit): 2

    • First, we know that 5 is represented in binary as 101.
    • Using the operation1<<2, we shift the number 1 to the left by two places to get 100, that is, < a i=4>. 4
    • Currently, I am the commander 5 (immediately 101) given 4 (immediately 100) Progress & Calculation, Gain 4. This is not 0, so the number 5 is the first 2 and the rank is 1.

おすすめ

転載: blog.csdn.net/weixin_64123373/article/details/132967688