牛客基础题全面提升 1

NC16644 字符串的展开

按照题目进行模拟,要考虑几种特殊情况,开头或结尾是-,或者中间有连续多个-

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

int p1 , p2 , p3;
string s;

void opt( char start , char end ){
    if( start + 1 == end ) return;
    if(  start == '-' || end == '-' || (end <= start) || ( start>='a' && start<='z' && end>='0' && start<='9' ) || ( start>='0' && start<='9' && end>='a' && start<='z' ) ){
        cout << "-";
        return;
    }
    if( p3 == 1 ){
        if( start >= 'a' && start <= 'z' && p1 == 2 )
            for( char it = start + 'A'-'a' + 1 ; it < end + 'A'-'a' ; it ++ )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << it;
        else
            for( char it = start+1 ; it < end ; it ++ )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << ( p1 == 3 ? '*' : it );
    }
    else {
        if( start >= 'a' && start <= 'z' && p1 == 2 )
            for( char it = end + 'A'-'a' - 1 ; it > start + 'A'-'a' ; it -- )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << it;
        else
            for( char it = end-1 ; it > start ; it -- )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << ( p1 == 3 ? '*' : it );
    }
}

int main()
{
    cin >> p1 >> p2 >> p3 >> s;
    int i;
    for( i = 0 ; i < s.size() ; i ++ )
    {
        if( s[i] != '-' ) break;
        cout<<"-";
    }
    for( ; i < s.size() ; i ++ )
    {
        if( s[i] == '-' ) opt( s[i-1] , s[i+1] );
        else cout << s[i];
    }
}

NC16622 多项式输出

特判指数为n 、1、0 三种情况

其次注意系数大于零要输出加好

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

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch<'0'||ch>'9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1) + ch-'0' , ch = getchar();
    return x*f;
}

int main()
{
    int n = read();
    for( int i = n , a ; i > 0 ; i -- )
    {
        a = read();
        if( a == 0 ) continue;
        if( n != i && a > 0 ) cout << "+";
        if( a == -1 ) cout << '-';
        if( abs(a) != 1 ) cout << a;
        if( i != 1 )cout << "x^"<<i;
        else cout << "x";
    }
    n = read();
    if( n > 0 ) cout << "+" << n;
    else if( n != 0 ) cout << n;

}

NC16593 铺地毯

注意一点的是输入的数据是左下角和长宽。

倒序枚举一下就好了。

#include <bits/stdc++.h>
#define int long long

using namespace std;

const int N = 10005;
int n , a[N][5];

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( ( ch < '0' || ch > '9' ) && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}
int32_t main()
{
    n = read();
    for( int i = 1 ; i <= n ; i ++ )
        for( int j = 1 ; j <= 4 ; j ++ ) a[i][j] = j > 2 ? a[i][j-2] + read() : read();
    int x = read() , y = read();
    for( int i = n ; i >= 1 ; i -- )
        if( a[i][1] <= x && a[i][2] <= y && a[i][3] >= x && a[i][4] >= y )
            printf("%lld\n" , i ) , exit(0);
    cout << "-1\n";
}

NC16438 回文日期

回文日期一年最多只有一天,先枚举出年份构造出回文日期判断日期是否合法就好

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

int sy , sm , sd , ey , em , ed , ss , ee;

int pending( int y , int m , int d )
{
    if( m > 12 || m < 1) return 0;
    switch (m) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            if( d > 31 ) return 0;
            else return 1;
        case 2: {
            if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) {
                if (d > 29) return 0;
                else return 1;
            } else {
                if (d > 28) return 0;
                else return 1;
            }
        }
        default: {
            if (d > 30) return 0;
            else return 1;
        }
    }
}

int main()
{
    scanf("%4d%2d%2d" , &sy , &sm , &sd );
    scanf("%4d%2d%2d" , &ey , &em , &ed );
    if( sy == ey && sm == em && sd == ed )
    {
        int k = sd%10;
        k = k * 10 + sd / 10 , k = k * 10 + sm % 10 , k = k * 10 + sm / 10;
        cout << (sy == k) << endl;
    }
    else {
        int ans = 0 , tm , td ;
        ss = sy * 10000 + sm * 100 + sd , ee = ey * 10000 + em * 100 + ed;
        for( int i = sy ; i <= ey ; i ++ )
        {
            tm = i%10*10 + i/10%10 , td = i/100%10*10+i/1000;
            ans += pending( i , tm , td );
        }
        cout << ans << endl;
    }
    return 0;
}

NC24636 值周

虽然可以 用查分来写,但是我发现可以进行区间合并,用总长度减去合并后的区间长度就好了

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

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main() {
    int n = read() + 1, m = read();
    vector<pair<int, int> > v;
    for (int l, r; m; m--)
        l = read(), r = read(), v.push_back({l, 0}), v.push_back({r, 1});
    sort( v.begin() , v.end() );
    int cnt = 0 , sta;
    for( auto [ x , t ] : v ){
        if( t == 0 ){
            if( cnt == 0 ) sta = x;
            cnt ++;
        }
        else{
            cnt --;
            if( cnt == 0 )
                n -= x - sta + 1;
        }
    }
    cout << n << endl;
}

NC235254 晾衣服

二分答案,判断一下,计算一下每一件衣服在规定时间晾干需要使用烘干机的次数

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

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
const int N = 1e5+5;
int n , a[N] ,k;

bool pending( int x ){
    int cnt = 0;
    for( int i = n ; a[i] > x ; i -- )
    {
        cnt += ( a[i] - x ) / ( k - 1 ) + ( ( a[i] - x ) % ( k - 1 ) > 0 );
        if( cnt > x ) return 0;
    }
    return 1;
}

int32_t main() {
    n = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    sort( a + 1 , a + 1 + n );
    k = read();
    if( k == 1 ) printf("%lld\n" , a[n] ) , exit(0);
    int l = 1 , r = 1e9 , mid , ans;
    while( l <= r ){
        mid = ( l + r ) >> 1;
        if( pending(mid) ) ans = mid , r = mid - 1;
        else l = mid + 1;
    }
    cout << ans << endl;
    return 0;
}

NC 14893 栈和排序

这道题要先预处理里出i...n中最大的数,在每次入栈前判断栈顶的数是否比i...n的最大值大,如果是就出栈重复操作之道不满足,然后在入栈。所有数入栈后清空栈就好了

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6+5;
int n , m , a[N] , b[N];
stack<int> stk;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main() {
    n = read();
    for( int i = 1 ; i <= n ; i ++ )
        a[i] = read();
    for( int i = n ; i >= 1 ; i -- )
        b[i] = max( a[i] , b[i+1] );
    for( int i = 1 ; i <= n ; i ++ ){
        while( stk.size() && stk.top() > b[i] )
        {
            cout << stk.top() << " ";
            stk.pop();
        }
        stk.push( a[i] );
    }
    while( stk.size() )
    {
        cout << stk.top() << " ";
        stk.pop();
    }
    return 0;
}

NC18386 字符串

这道题几乎就是双指针的模板题了。

每次移动一下左端点,然后移动右端点知道满足条件

#include<bits/stdc++.h>

using namespace std;

int v[300] = {};

int32_t main() {
    string s;
    cin >> s;
    int l = 0 , r = -1 , len = s.size() , ans = 1e9 , k = 0;
    while( l < len ){
        while( r < len - 1 && k < 26 ) { // 右指针右移
            r++, v[s[r]]++;
            if (v[s[r]] == 1) k++;
        }

        if( k == 26 ) ans = min( ans , r - l + 1 ); // 满足条件

        if( v[s[l]] == 1 ) k --; // 左指针右移
        v[s[l]] -- , l ++;
        }
    cout << ans << endl;
    return 0;
}

NC207040 丢手绢

这道题也可以用双指针来做。但是值得注意的是因为圆的性质,所以圆上两点之间的距离一定是小于等于半径的。所以如果右指针移动后距离大于半径了,右指针的移动就可以结束了。

#include<bits/stdc++.h>

using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e5+5;
int n , a[N] , ans , sum , cnt ;

int32_t main() {
    n = read();
    for( int i = 0 ; i < n ; i ++ )
        a[i] = read() , sum += a[i];
    for( int i = 0 , j = -1 ; i < n ; i ++ )
    {
        while( cnt * 2 < sum ){
            j = ( j +1 ) % n , cnt += a[j];
            ans = max( ans , min( cnt , sum - cnt ) );
        }
        cnt -= a[i];
    }
    cout << ans << endl;
    return 0;
}

NC15173 The Biggest Water Problem

递归的操作就好了

#include<bits/stdc++.h>

using namespace std;

void dfs( int x ){
    if( x < 10 ){
        cout << x;
        exit(0);
    }
    int y = 0;
    while( x ) y += x % 10 , x /= 10;
    dfs(y);
    return;
}

int32_t main() {
    int x;
    cin >> x;
    dfs(x);
    return 0;
}

NC16644 字符串的展开

模拟题

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

int p1 , p2 , p3;
string s;

void opt( char start , char end ){
    if( start + 1 == end ) return;
    if(  start == '-' || end == '-' || (end <= start) || ( start>='a' && start<='z' && end>='0' && start<='9' ) || ( start>='0' && start<='9' && end>='a' && start<='z' ) ){
        cout << "-";
        return;
    }
    if( p3 == 1 ){
        if( start >= 'a' && start <= 'z' && p1 == 2 )
            for( char it = start + 'A'-'a' + 1 ; it < end + 'A'-'a' ; it ++ )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << it;
        else
            for( char it = start+1 ; it < end ; it ++ )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << ( p1 == 3 ? '*' : it );
    }
    else {
        if( start >= 'a' && start <= 'z' && p1 == 2 )
            for( char it = end + 'A'-'a' - 1 ; it > start + 'A'-'a' ; it -- )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << it;
        else
            for( char it = end-1 ; it > start ; it -- )
                for( int j = 1 ; j <= p2 ; j ++ )
                    cout << ( p1 == 3 ? '*' : it );
    }
}

int main()
{
    cin >> p1 >> p2 >> p3 >> s;
    int i;
    for( i = 0 ; i < s.size() ; i ++ )
    {
        if( s[i] != '-' ) break;
        cout<<"-";
    }
    for( ; i < s.size() ; i ++ )
    {
        if( s[i] == '-' ) opt( s[i-1] , s[i+1] );
        else cout << s[i];
    }
}

NC24739 Lake Counting

从每一个是湖且没有被访问过的点开始进行dfs,统计dfs的次数就是答案

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


const int N = 105 , dx[] = { 0 , 0 , 1 , 1 , 1 , -1 , -1 , -1 } , dy[] = { 1 , -1 , 1 , -1 , 0 , 1 , 0 , -1 };
int n , m , v[N][N] , cnt;

void dfs( int x , int y )
{
    if( x < 1 || y < 1 || x > n || y > m ) return ;
    if( v[x][y] ) return;
    v[x][y] = 1;
    for( int i = 0 ; i < 8 ; i ++ ) dfs( x + dx[i] , y + dy[i] );
    return;
}

int main()
{
    cin >> n >> m;
    for( int i = 1 ; i <= n ; i ++ )
    {
        for( int j = 1 , x ; j <= m ; j ++ )
        {
            do{
                x = getchar();
            }while( x != '.' && x != 'W' );
            if( x == '.' ) v[i][j] = 1;
        }
    }
    for( int i = 1 ; i <= n ; i ++ )
    {
        for( int j = 1 ; j <= m ; j ++ )
        {
            if( v[i][j] ) continue;

            cnt ++;
            dfs( i , j );
        }
    }
    cout << cnt << endl;
    return 0;
}

NC16710 最大公约数

模板

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

int main(){
    long long a , b;
    cin >> a >> b;
    cout << a / __gcd( a , b ) * b << endl;
}

NC16649 校门外的树

可以用区间合并来做,但是这里只要用差分来维护一下那些书被移走了就好

#include<bits/stdc++.h>

using namespace std;

const int N = 10005;
int L , m , res;
int a[N];

int main(){
    cin >> L >> m;
    for( int i = 1 , l , r ; i <= m ; i ++ ) {
        cin >> l >> r ;
        a[l] ++ , a[r+1] --;
    }
    for( int i = 1 ; i <= L ; i ++ )
        a[i] += a[i-1];
    for( int i = 0 ; i <= L ; i ++ )
        res += ( a[i] == 0 );
    cout << res << endl;
    return 0;
}

NC21874 好串

一道看似复杂的题,把a当做(,把b当做)那么这就是一道括号匹配的问题

因为种类单一甚至不需要用到栈就可以解决

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

int main(){
    string s;
    int tp = 0;
    cin >> s;
    for( auto it : s ){
        if( it == 'a' ) tp ++;
        else{
            if( tp == 0 ){
                cout << "Bad\n";
                return 0;
            }
            tp --;
        }
    }
    if( tp ){
        cout << "Bad\n";
        return 0;
    }
    cout << "Good\n";
    return 0;
}

NC223888 红色和紫色

两个人都安装棋盘格的形式来涂颜色,所以就是问谁是最后一个下手的,这样的话判断格子总数的奇偶就好了

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

int main(){
    int n , m;
    cin >> n >> m;
    if( n & 1 && m & 1 )
        cout << "akai\n";
    else
        cout << "yukari\n";
    return 0;
}

NC208813 求逆序对数

暴力解法就是直接循环就好了

#include<bits/stdc++.h>

using namespace std;

const int N = 2005;
int n , a[N] , res;

int32_t main() {
    cin >> n;
    for( int i = 1 ; i <= n ; i ++ )
        cin >> a[i];
    for( int i = 1 ; i <= n ; i ++ ) 
        for( int j = 1 ; j < i ; j ++ )
            if( a[j] > a[i] ) res ++;
    cout << res << endl;
    return 0;
}

但是可以用树状数组来求一下,但是需要 hash 一下才可以

NC23050 华华对月月的忠诚

gcd(f[n],f[n+1]) = gcd( f[n+1]-f[n] , f[n] ) = gcd( f[n-1] , f[n] )不断递推就可以得到

gcd(f[n],f[n+1]) = gcd( f[2] , f[1] )

#include<bits/stdc++.h>

using namespace std;

int32_t main() {
    long long a , b;
    cin >> a >> b;
    cout << __gcd( a , b );
    return 0;
}

NC235813 N皇后问题

通过dfs的方式进行枚举,枚举每一行的皇后位于那一列,可以通过一个数组来记录下哪一列有皇后,皇后在一条对角线上的情况就是两个皇后连线的斜率是正负1

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

const int N = 15;
int n , row[N] , res;
bool colum[N];

void dfs( int x ){
	if( x > n ){
		res ++;
		return ;
	}
	for( int i = 1 , f = 1 ; i <= n ; i ++ , f = 1 ){
		if(colum[i] ) continue;
		for( int j = 1 ; j < x && f ; j ++ ) // 判断对角线
			if( abs( row[j] - i ) == abs( j - x ) ) f = 0;
		if( !f ) continue;
		colum[i] = 1 , row[x] = i;
		dfs( x + 1 );
		colum[i] = 0;
	}
}

int main(){
	cin >> n;
	dfs( 1 );
	cout << res << "\n";
}

NC18979 毒瘤xor

因为是异或操作,所以可以转化成对二进制考虑,统计一下每一位是0多还是1多,0多这一位就是1,防止就是0,相同的因为输出较少的所以也是0

统计个数可以用前缀和处理

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+5 , M = 35;
int n , pre[N][M];

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

void f( int val , int t ){
    for( int i = 0 ; val ; i ++)
        pre[t][i] = val & 1 , val /= 2;
}

int32_t main() {
    n = read();
    for( int x , i = 1 ; i <= n ; i ++ )
        x = read() , f( x , i );
    for( int t = 0 ; t <= 31 ; t ++ )
        for( int i = 1 ; i <= n ; i ++ ) pre[i][t] += pre[i-1][t];
    for( int m = read() , l , r , len , res ; m ; m -- ){
        l = read() , r = read() , len = r - l + 1 , res = 0;
        for( int i = 0 ; i <= 30 ; i ++ )
            if( (pre[r][i] - pre[l-1][i]) * 2 < len )  res += (1<<i);
        printf("%lld\n" , res );
    }
    return 0;
}
posted @ 2022-08-10 20:38  PHarr  阅读(26)  评论(0编辑  收藏  举报