2021_ 07_ 20 (double pointer & ruler & discretization & introduction to stl partial containers & struct rewriting)

Posted by aosmith on Fri, 14 Jan 2022 13:50:01 +0100

A - Sum of Consecutive Prime Numbers

Given a positive integer, query how many satisfy its sum and can be expressed by continuous quality.

Idea: because the num of this problem itself is not very large (10000), it contains fewer prime numbers. You can find all prime numbers and use a ruler to take them.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
vector< ll > v;
ll sum[10010];
int main()
{
    ios :: sync_with_stdio( false );
    cin.tie( NULL );
    v.push_back(2);
    for( ll i = 3; i <= 10000; i++ ){
        int f = 1;
        for( ll j = 2; j <= sqrt( i * 1.0 ); j++ ){
/*

This error shows that the parameters behind the sqrt function can only be long double, float or double data,
If you give it an integer parameter, the system will report an error and don't know which to use. There are two ways. One is to use strong rotation,
One is to multiply by 1.0 to make the system automatically convert to decimal.

*/
            if( i % j == 0 ){
                f = 0;
                break;
            }
        }
        if( f ){
            v.push_back(i);
        }
    }//This problem first needs prime numbers to make a table. In fact, there is a more advanced method - prime sieve, which will not be mentioned here.
    ll len = v.size();
    sum[0] = 0;
    for( ll i = 1; i < len; i++ ){
        sum[i] = sum[i - 1] + v[i - 1];
    }//At first, I wanted to use prefix and, but in fact, it's superfluous. The later question will come here.
    ll num;
    while( cin >> num && num != 0 ){
        ll l = 0, r = 0;
        ll res = v[0];
        ll cnt = 0;
        while( l < len && r < len ){
            while( res < num && r < len ){
                ++r;
                res = sum[r] -sum[l] + v[r];
            }
            if( res == num ){
                ++cnt;
                ++l;
                res = sum[r] -sum[l] + v[r];
            }
            while( res > num && l < len){
                ++l;
                res = sum[r] -sum[l] + v[r];
            }
        }
        cout << cnt << endl;
    }
    return 0;
}

C - Graveyard Design

Question meaning: enter a number (1 < = n < = 10 ^ 14) to see how many sequences satisfy that the number in this sequence is a continuous natural number, and the sum of the squares of the numbers at each position in the sequence is equal to the entered number.

Idea: when I first started this problem, I experienced timeout, array overflow, crying, Later, I found that there was a problem in understanding the ruler. It was uncomfortable. It was terrible that the question above had passed in this way. It was uncomfortable

This problem is also equivalent to a board taken by a ruler.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
int main()
{
    ios :: sync_with_stdio( false );
    cin.tie( NULL );
    ll num;
    cin >> num;
    ll l = 1, r = 1;//At first, both hands pointed to the head
    ll res = 0;
    ll len = sqrt( num * 1.0 );//Reduce range
    vector< pair< ll, ll > > v;//Use a pair to record the left and right boundaries of the sequence
    while( true ){
    while( res < num && r <= len){
            //If the current scale is still less than num, the right pointer will always move to the right, but make sure not to cross the boundary.
            res += r * r;
            ++r;
        }
        //If you exit from the while above, it means either res > = num or R > len;
     
        if( res < num ){
            break;
        }
        //If the while above is still less than num,
        //That means that this sequence can never meet the condition again, because r has reached the tail

        
        if( res == num && l <= len){
            v.push_back( make_pair( l, r - 1 ) );
        }
        //If the above conditions are met, it is added to the queue

          res -= l * l;
          ++l;
        //Here, in order to facilitate code writing, we specify to move l to the right whether it is greater than or equal to.
    }
    len = v.size();
    cout << len << endl;
    for( ll i = 0; i < len; i++ ){
        cout << v[i].second - v[i].first + 1;
        for( ll j = v[i].first; j <= v[i].second; j++ ){
            cout << " " << j;
        }
        cout << endl;
    }
    return 0;
}

D - Hyperset

Question meaning: input n strings of length k, and this string only contains three characters'S','E','T ', and the N strings are different. Find out how many pairs (three in a team) satisfy that the characters in the corresponding position are either equal or complementary (SET).

Idea: arbitrarily enumerate two strings, find the corresponding string through the two strings, and then find out whether there is such a string in the whole string. Note that this idea will often be encountered in the future: it is generally constant, but the hard run will timeout, so consider merging. This problem has some ingenious points: 1. Record the conversion of 2, int, char and string through ascall code. int sum = 'A' + 'B' + 'C'; string s; s += sum - 'A' - 'B'; PS: divide the result by 3.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
int sum = 'S' +'E' +'T';
int main()
{
    ios :: sync_with_stdio( false );
    cin.tie( NULL );
    int n, k;
    cin >> n >> k;
    string s[1510];
    set< string > st;
    for( int i = 0; i < n; i++ ){
        cin >> s[i];
        st.insert( s[i] );
    }
    long long ans = 0;
    for( int i = 0; i < n; i++ ){
        for( int j = i + 1; j < n; j++ ){
            string res;
            for( int f = 0; f < k; f++ ){
                if( s[i][f] == s[j][f] ){
                    res += s[i][f];
                }
                else{
                    res += sum - s[i][f] - s[j][f];
                }
            }
        ans += st.count( res );    
        }
    }
    cout << ans / 3;
    return 0;
}

B - Dyson Box

Given the position of N blocks, there are n cases, and each case is accumulated on the above case. Calculate the perimeter of the figure formed when gravity is down and left respectively.

Idea: This is a thinking + stl container problem. Obviously, the perimeter contribution of each cube is normally 4, but in some cases, the contribution will be reduced. For gravity down, when there are other blocks in its column, its contribution value will be - 2. When the total number of blocks in its previous column (the latter column) is greater than its own column, the total number of blocks will be - 2. The direction of gravity is the same to the left. How to record? Two map s are used to record the number of blocks in each row and column respectively.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
map< ll, ll > mp1, mp2;
int main()
{
    ios :: sync_with_stdio( false );
    cin.tie( NULL );
    ll n, x, y;
    cin >> n;
    ll vans = 0, hans = 0;
    while( n-- ){
        cin >> x >> y;
        vans += 4; hans += 4;
        if( mp1[x] )
            vans -= 2;
        if( mp2[y] ) 
            hans -= 2;
        if( x != 0 && mp1[x - 1] > mp1[x] )//Pay attention to the details and don't cross the array
            vans -= 2;
        if( y != 0 && mp2[y - 1] > mp2[y] )
            hans -= 2;    
        if( mp1[x + 1] > mp1[x] )
            vans -= 2;
        if( mp2[y + 1] > mp2[y] )
            hans -= 2;
        ++mp1[x]; ++mp2[y];//Note that this can't be placed in the front. Check it first and then put it
        cout << vans << " " << hans << endl;
    }
    return 0;
}

Summary:

I learned more common stl containers, basic ruler knowledge and classic exercises, and had a certain understanding of discretization. Discretization maps finite individuals in infinite space to finite space, so as to improve the space-time efficiency of the algorithm. Generally speaking, discretization is to reduce the data without changing the relative size of the data.

vector:

v[ i ]:

v.empty( );

v.size();

v.clear( );

initialization: vector initialization summary

set :

s.clear( );

s.insert( );

s.erase( );

s. Erase (first, last) / / delete all elements within the iterator range

s.count() / / query whether the number exists. If it exists, it returns 1. Otherwise, it returns 0

s.empty( );

s.size();

find(x): when there is an element with key X in set, the iterator of the element will be returned; otherwise, end() will be returned.

map:

m.count( );

m.find( );

s.empty( );

s.size();

Topics: Algorithm