春季测试补题

P9117 [春季测试 2023] 涂色游戏

显然 后面的操作会覆盖前面的操作 那么我们为每一行和每一列记录一个颜色和时间戳

最后输出的时候比较行列时间戳的最大值对应的颜色即可

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 1e6 + 5;

int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
} 

int n , m , q , len[N] , timlen[N] , row[N] , timrow[N];

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    int T = read();
    while ( T -- )
    {
        memset ( len , 0 , sizeof len );
        memset ( timlen , 0 , sizeof timlen );
        memset ( row , 0 , sizeof row );
        memset ( timrow , 0 , sizeof timrow );
        n = read() , m = read() , q = read();
        for ( int i = 1 ; i <= q ; i ++ )
        {
            int op = read() , x = read() , c = read();
            if ( op == 0 ) timlen[x] = i , len[x] = c;
            else timrow[x] = i , row[x] = c;
        }
        for ( int i = 1 ; i <= n ; i ++ , cout.put(endl) )
            for ( int j = 1 ; j <= m ; j ++ )
                cout << ( timlen[i] > timrow[j] ? len[i] : row[j] ) << ' ';
    }
    return 0;
}

P9118 [春季测试 2023] 幂次

数据分治:

  1. \(k=1\) 直接输出 \(n\) 即可
  2. \(k\ge 3\)\(2\) 开始枚举底数 暴力枚举指数即可 所有合法底数上界为 \(\sqrt[3]n\) 足以通过 注意需要加上 \(1^1=1\) 的情况
  3. \(k=2\) 考虑优化 因为 \(\sqrt[2]n\)\(1e9\) 级别的 那么我们可以在沿用 \(2\) 方法的基础上 忽略所有的完全平方数 让最后的答案加上 \(\sqrt n\) 即可(因为 \(n\) 以内的完全平方数个数即为 \(\sqrt n\))

注意开 \(\_\_int128\)\(long\ double\)

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
#define int __int128
const int N = 1e6 + 5;

int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
} 

void write ( int x )
{
    if ( x < 0 ) x = -x , cout.put ( '-' );
    if ( x > 9 ) write ( x / 10 );
    cout.put ( x % 10 + '0' );
}

int n , k , ans;

map<int,int> mp;

int ksm ( int base , int k )
{
    int res = 1;
    for ( ; k ; base *= base , k >>= 1 )   
        if ( k & 1 ) res *= base;
    return res;
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    n = read() , k = read();
    if ( k == 1 ) return write(n) , cout.put(endl) , 0;
    else if ( k >= 3 )
    {
        ans = 1;
        for ( int i = 2 ; i <= n ; i ++ )
        {
            if ( ksm ( i , k ) > n ) break;
            int cur = ksm ( i , k );
            for ( int j = k ; ; j ++ )
            {
                if ( cur > n ) break;
                if ( !mp.count ( cur ) ) ++ ans , mp[cur] = 1;
                cur *= i;
            }
        }
        write(ans);
    }
    else 
    {
        for ( int i = 2 ; i <= n ; i ++ )
        {
            if ( ksm ( i , 3 ) > n ) break;
            int cur = ksm ( i , 3 );
            for ( int j = 3 ; ; j ++ )
            {
                if ( cur > n ) break;
                if ( !mp.count ( cur ) && ! ( (int)sqrtl((long long)cur) * (int)sqrtl((long long)cur) == cur ) ) ++ ans , mp[cur] = 1;
                cur *= i;
            }
        }
        write(ans+(int)sqrtl((long long)n));
    }
    return 0;
}

P9119 [春季测试 2023] 圣诞树

乱搞 \(95pts\)

对于 \(n\le 9\) 的点 全排列即可通过 (\(30pts\))

对于 \(n\le 18\) 可以状压 (\(60pts\))

对于性质 \(B\) 直接顺序输出即可

对于其他点 充分发扬人类智慧 将所有的点按照 \(y\) 坐标进行排序输出即可

注意 \(long\ double\)

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 1e6 + 5;
const double inf = 0x3f3f3f3f;

int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
} 

int n , k , temp[N] , t[N];
double res , minn = inf , maxxy;

struct node { double x , y; int id; } a[N];

double dis ( node a , node b ) { return sqrtl ( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) ); }

namespace sub1
{
    void main()
    {
        for ( int i = 1 ; i <= n ; i ++ ) t[i] = i;
        do
        {
            if ( t[1] != k ) continue;
            double tt = 0;
            for ( int i = 1 ; i < n ; i ++ ) tt += dis ( a[t[i]] , a[t[i+1]] );
            if ( tt < minn ) memcpy ( temp , t , sizeof t ) , minn = tt;
        } while ( next_permutation ( t + 1 , t + n + 1 ) );
        for ( int i = 1 ; i <= n ; i ++ ) cout << temp[i] << ' ';
    }
}

namespace sub2
{
    int g[N][20];
    double f[N][20];
    vector<int> ans;
    void main ()
    {
        for ( int s = 0 ; s < ( 1 << n ) ; s ++ )
            for ( int j = 1 ; j <= n ; j ++ ) f[s][j] = inf;
        f[1<<k-1][k] = 0;
        for ( int s = 0 ; s < ( 1 << n ) ; s ++ )
            for ( int i = 1 ; i <= n ; i ++ )//pre
                if ( ( s & 1 << i - 1 ) && f[s][i] != inf )
                   for ( int j = 1 ; j <= n ; j ++ )//now
                        if ( f[s|1<<j-1][j] > f[s][i] + dis ( a[i] , a[j] ) && ! ( s & 1 << j - 1 ) )
                            f[s|1<<j-1][j] = f[s][i] + dis ( a[i] , a[j] ) , g[s|1<<j-1][j] = i;
        int ed = 0 , s = (1<<n) - 1 , temp;
        double minn = inf;
        for ( int i = 1 ; i <= n ; i ++ ) if ( minn > f[s][i] ) minn = f[s][i] , ed = i;
        while ( ed ) ans.eb(temp=ed) , ed = g[s][ed] , s ^= 1 << temp - 1;
        reverse ( ans.begin() , ans.end() );
        for ( auto v : ans ) cout << v << ' ';
    }
}

namespace sub3
{
    void solve ()
    {
        sort ( a + 1 , a + n + 1 , [](const node &a , const node &b ) { return a.y == b.y ? a.id < b.id : a.y > b.y; } );
        for ( int i = 1 ; i <= n ; i ++ ) cout << a[i].id << ' ';
    }
    void solveB() { for ( int i = 1 ; i <= n ; i ++ ) cout << i << ' '; }
    void main ()
    {                                        
        int pdb = 1;
        for ( int i = 1 ; i < n ; i ++ ) if ( a[i].x > a[i+1].x || a[i].y < a[i+1].y ) { pdb = 0; break; }
        if ( pdb ) solveB();
        else solve();
    }
}

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    n = read();
    for ( int i = 1 ; i <= n ; i ++ )
    {
        cin >> a[i].x >> a[i].y , a[i].id = i;
        if ( a[i].y > maxxy ) k = i , maxxy = a[i].y;
    }
    if ( n <= 9 ) sub1::main();
    else if ( n <= 18 ) sub2::main();
    else sub3::main();
    return 0;
}

P9120 [春季测试 2023] 密码锁

\(random\_shuffle\) 大法好

\(25pts\) 性质+暴搜显然

对于后面的点 我们考虑一个错误贪心:从 \(1\)\(n\) 来贪心 枚举每一种挂锁状态对于答案的贡献 取最小贡献累加即可

但这种贪心是有后效性的 但是对于一些特定的顺序可以解出正确的解

那么我们 \(random\_shuffle\) \(200\) 次 就有很大概率解出正解()

赛时 \(25pts\) 代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define inl inline
const int N = 3e5 + 5;
const int inf = 4e18;
inl int read()
{
	int f = 1 , x = 0;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = x * 10 + ( ch - '0' ); ch = getchar(); }
	return x * f;
}
int T , k , n , a[N] , mp[5][N] , temp[5][N] , ans = inf;

void dfs ( int stp )
{
	if ( stp == n + 1 ) 
	{
		int maxx , minn , anstemp = -inf;
		for ( int i = 1 ; i <= k ; i ++ ) 
		{
			maxx = -inf , minn = inf;
			for ( int j = 1 ; j <= n ; j ++ )
				maxx = max ( temp[i][j] , maxx ) , minn = min ( temp[i][j] , minn );
			anstemp = max ( anstemp , maxx - minn );
		}
		ans = min ( anstemp , ans );
		return;
	}
	for ( int tt = 1 ; tt <= k ; tt ++ )
	{
		for ( int i = 1 ; i <= k ; i ++ ) temp[i][stp] = mp[(i+tt)%k+1][stp];
		dfs ( stp + 1 );
		for ( int i = 1 ; i <= k ; i ++ ) temp[i][stp] = 0;
	}
}
void solve ()
{
	while ( T -- )
	{
		ans = inf;
		n = read();
		for ( int i = 1 ; i <= k ; i ++ )
			for ( int j = 1 ; j <= n ; j ++ )
				mp[i][j] = read();
		dfs ( 1 );
		printf ( "%lld\n" , ans );
	}
}

signed main ()
{
	T = read() , k = read();
	if ( k == 1 )
	{
		while ( T -- )
		{
			n = read();
			int maxx = -inf , minn = inf;
			for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , maxx = max ( a[i] , maxx ) , minn = min ( a[i] , minn );
			printf ( "%lld\n" , maxx - minn );
		}
	}
	else solve();
	return 0;
}

\(100pts\): 纯随机化

#include<bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define inl inline
#define eb emplace_back
#define endl '\n'
#define pii pair<int,int>
#define mkp make_pair
#define fi first
#define se second
#define print(x) cerr<<#x<<'='<<x<<endl
#define getchar() cin.get()
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f;

int read()
{
	int x = 0 , f = 1;
	char ch = getchar();
	while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
	while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
	return x * f;
} 

int n , k , a[N][10] , maxx[10] , minn[10];

signed main ()
{  
    // freopen ( "lock2.in" , "r" , stdin );
    srand(random_device{}());
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    int T = read() , k = read();
    while ( T -- )
    {
        n = read();
        for ( int i = 1 ; i <= k ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) a[j][i] = read();
        int cnt = 200 , ans = inf;
        for ( int i = 1 ; i <= cnt ; i ++ )
        {
            random_shuffle ( a + 1 , a + n + 1 );
            //这里的random只会改变行上下的位置
            memset ( maxx , -inf , sizeof maxx );
            memset ( minn , inf , sizeof minn );
            for ( int j = 1 ; j <= n ; j ++ )
            {
                int tempval = inf , minstp = 0;
                for ( int stp = 0 ; stp < k ; stp ++ )
                {
                    int kk = 0;
                    for ( int x = 1 ; x <= k ; x ++ )
                    {
                        int tmp = ( x + stp - 1 ) % k + 1;
                        kk = max ( kk , max ( maxx[x] , a[j][tmp] ) - min ( minn[x] , a[j][tmp] ) );
                    }
                    if ( kk < tempval ) tempval = kk , minstp = stp;
                }
                for ( int x = 1 ; x <= k ; x ++ )
                {
                    int tmp = ( x + minstp - 1 ) % k + 1;//最优情况下转多少圈
                    maxx[x] = max ( maxx[x] , a[j][tmp] );
                    minn[x] = min ( minn[x] , a[j][tmp] );
                }
                // cout << n << ' < endl;' << j << "check" << endl;
                // for ( int l = 1 ; l <= k ; l ++ ) cout << maxx[l] << ' ' << minn[l] << endl;
                // cout << "check1" <
                if ( tempval >= ans ) break;
            }
            // for ( int i = 1 ; i <= k ; i ++ , cout.put(endl) ) for ( int j = 1 ; j <= n ; j ++ ) cout << a[j][i] << ' ';
            int res = 0;
            for ( int j = 1 ; j <= k ; j ++ ) res = max ( res , maxx[j] - minn[j] );
            ans = min ( ans , res );
        }
        cout << ans << endl;
    }
    return 0;
}

/*
2 3
2
1 2
2 1
1 2
3
1 2 1
2 3 2
3 1 3
*/
posted @ 2023-10-13 15:20  Echo_Long  阅读(23)  评论(0编辑  收藏  举报