Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) A模拟 B数学 C 数学 D 暴力

A

#include <bits/stdc++.h>
using namespace std;
const int AX = 1e3+66;
struct Node{
    int id,s;
    bool friend operator < ( const Node &a , const Node &b ){
        if(a.s != b.s) return a.s > b.s;
        else return a.id < b.id;
    }
}G[AX];
int a, n, b, c, d;

int main() {
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        cin >> a >> b >> c >> d;
        G[i].id = i;
        G[i].s = a+b+c+d;
    }
    sort(G+1,G+1+n);
    for(int i = 1; i <= n; i ++) 
        if(G[i].id == 1) return 0*printf("%d\n",i);
    return 0;
}

B
题意:给两个串s,t,要求反转s中任意两个字母,使得 两个0,1串或值改变。
思路:t是0,s对应位置为0时,找s中1交换,t是1,s对应位置是0,找s中0交换,最后减去重复的。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int AX = 1e5+66;
char a[AX];
char b[AX];
int main(){
    int n ;
    scanf("%d",&n);
    scanf("%s%s",a+1,b+1);
    int cur = 0 ;
    long long res = 0 ;  
    long long x = 0 , y = 0 , x1 = 0 , y1 = 0 ;
    for( int i = 1 ; i <= n ; i++ ){
        if( b[i] == '0' && a[i] == '0' ){
            x ++ ;
        }
        if( b[i] == '0' && a[i] == '1' ){
            y ++ ;
        }
        if( a[i] == '0' ) x1++ ;
        else y1 ++ ;
    }
    cout << ( x1*y + x*y1 - x * y) << endl;
    return 0 ;
}

C
题意:要求输出一个1-n的全排列,使得LIS+LDS长度最小
思路:每段长度sqrt(n)输出
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int AX = 1e6+6;
int a[AX];
int main(){
    int n;
    scanf("%d",&n);
    int len = sqrt(n);
    int tot = n ;
    for( int i = 1 ; i <= n ; i += len ){
        for( int j = min( i + len - 1 , n ) ; j >= i ; j-- ){
            a[j] = tot--;
        }
    }
    for( int i = 1 ; i <= n ; i++ ){
        printf("%d%c",a[i],"\n "[i<n]);
    }
    return 0 ;
}

D
题意:给n为每个串长度,还有n个值,对应每个位置的价值,m个串,q个询问。要求每个询问输入一个串和一个价值,输出m个串里面与这个串相同位置价值之和小于给的价值(<100)的个数。
思路:n的范围是12,(1<<12==4096),可以预处理出所有值到m中所有串的和<100的个数,然后再求个前缀和,查询的时候直接输出即可。
Code:

#include <bits/stdc++.h>
#pragma comment(linker, “/STACK:1024000000,1024000000”)
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int AX = 5e3;
int a[20];
int sum[AX][102];
int num[AX];
int main(){
    int n , m , q ;
    scanf("%d%d%d",&n,&m,&q);
    for( int i = 0 ; i < n ; i++ ){
        scanf("%d",&a[i]);
    }

    char s[20];
    for( int i = 0 ; i < m ; i++ ){
        scanf("%s",s);
        int tmp = 0 ;
        for( int j = n - 1 ; j >= 0 ; j-- ){
            if( s[j] == '1' ){
                tmp += ( 1 << (n-1-j) );
            }
        }
        num[tmp] ++;
    }
    int MAX = ( 1 << n );
    for( int i = 0 ; i < MAX ; i++ ){
        for( int j = 0 ; j < MAX ; j++ ){
            if( num[j] ){
                int tmp = 0 ;
                for( int k = 0 ; k < n ; k++ ){
                    if( ( i & ( 1 << k ) ) == ( j & ( 1 << k ) ) ){
                        tmp += a[n-k-1];
                    }
                }
                if( tmp <= 100 ){
                    sum[i][tmp] += num[j];
                }               
            }
        }
    }
    for( int i = 0 ; i <= MAX ; i++ ){
        for( int j = 1 ; j <= 100 ; j++ ){
            sum[i][j] += sum[i][j-1];
        }
    }
    int v ;
    while( q-- ){
        scanf("%s%d",s,&v);
        int tmp = 0 ;
        for( int j = n - 1 ; j >= 0 ; j-- ){
            if( s[j] == '1' ){
                tmp += ( 1 << (n-1-j) );
            }
        }
        printf("%d\n",sum[tmp][v]);
    }
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/FrankAx/article/details/81537912