CF1598

Computer Game

深搜,启动!

#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define eb emplace_back
#define pb pop_back
#define endl '\n'
#define mid (l+r>>1)
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define getchar() cin.get()
const int dx[9] = { 0 , 1 , 0 , -1 , 1 , 1 , -1 , -1 };
const int dy[9] = { 1 , 0 , -1 , 0 , 1 , -1 , 1 , -1 };
const int N = 1e2 + 5;
 
int read()
{
	int f = 1 , x = 0;
	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 , flag , vis[3][N];
char mp[3][N];
 
inl int check ( int x , int y ) { return 1 <= x && x <= 2 && 1 <= y && y <= n && mp[x][y] == '0'; }
 
void dfs ( int x , int y )
{
	if ( x == 2 && y == n ) return flag = 1 , void();
	for ( int i = 0 ; i < 8 ; i ++ )
	{
		int tx = x + dx[i] , ty = y + dy[i];
		if ( vis[tx][ty] || !check(tx,ty) ) continue;
		vis[tx][ty] = 1 , dfs ( tx , ty );
	}
}
 
signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
	int T = read();
	while ( T -- )
	{
		flag = 0;
		memset ( vis , 0 , sizeof vis );
		n = read();
		for ( int i = 1 ; i <= 2 ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) cin >> mp[i][j];
		vis[1][1] = 1;
		dfs ( 1 , 1 );
		cout << ( flag ? "YES" : "NO" ) << endl;
	}
	return 0;
}

Groups

考虑枚举两个不同的时间点进行比对。

记录 \(cnt1\) 为第一种课的人数,\(cnt2\) 为第二种课的人数,\(cnt\) 为两个课的交集。

那么合法条件为 \(cnt1\ge \frac n 2 \and cnt2\ge \frac n2\and cnt1+cnt2-cnt\ge n\)

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define getchar() cin.get()
const int N = 1e3 + 5;
const int mod = 1e9 + 7;

int read()
{
	int f = 1 , x = 0;
	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 , a[N][6];

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    int T = read();
    while ( T -- )
    {
        n = read();
        for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= 5 ; j ++ ) a[i][j] = read();
        for ( int j = 1 ; j <= 5 ; j ++ )
            for ( int k = j + 1 ; k <= 5 ; k ++ )
            {
                int cnt1 = 0 , cnt2 = 0 , cnt = 0;
                for ( int i = 1 ; i <= n ; i ++ )
                {
                    cnt1 += a[i][j];
                    cnt2 += a[i][k];
                    cnt += ( a[i][j] && a[i][k] );
                }
                if ( cnt1 >= n / 2 && cnt2 >= n / 2 && cnt1 + cnt2 - cnt >= n ) { cout << "YES" << endl; goto flg; }
            }
        cout << "NO" << endl;
        flg:;
    }
}

Delete Two Elements

推一下柿子:(设我们现在到的点为 \(i\)

我们要求的就是满足这样的柿子的方案数:\(\frac {sum} n=\frac {sum-a_i-a_x} {n-2},x<i\)

\(a_x=\frac{2\times sum} n-a_i\)

因为数列中都是整数,那么当 \(\frac {2\times sum} n\) 不为整数的时候显然无解。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define getchar() cin.get()
#define int long long
const int N = 2e5 + 5;

int read()
{
	int f = 1 , x = 0;
	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 , ans , k , a[N];

map<int,int> mp;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    int T = read();
    while ( T -- )
    {
        ans = 0 , k = 0 , mp.clear();
        n = read();
        for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , k += a[i];
        k *= 2;
        if ( k % n ) { cout << 0 << endl; continue; }
        k /= n;
        for ( int i = 1 ; i <= n ; i ++ ) ans += mp[k-a[i]] , mp[a[i]] ++;
        cout << ans << endl;
    }
}   

Training Session

计数题。

首先考虑正向计数,发现答案为满足 \(a\) 三个不相同和满足 \(b\) 三个不相同的方案数的加和,还要减去同时满足 \(a\) 三个不相同和 \(b\) 三个不相同的方案数量,比较麻烦。

正难则反,我们用总数减掉不合法的情况。

显然总操作次数为 \(C_n^3=\frac {n\times(n-1)\times(n-2)}6\)

因为没有两个相等的点对,那么不合法的情况一定是当前这个点对和一个相同的 \(a\) 和一个相同的 \(b\) 组成。

因为如果是三个相同的 \(a\),那么三个 \(b\) 一定是互不相同的,三个相同的 \(b\) 同理。

那么乘法计数一下即可。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define getchar() cin.get()
#define int long long
const int N = 2e5 + 5;
const int mod = 1e9 + 7;

int read()
{
	int f = 1 , x = 0;
	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 , a[N] , b[N] , ans;

map<int,int> mpa , mpb;

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    int T = read();
    while ( T -- )
    {
        n = read() , ans = n * ( n - 1 ) * ( n - 2 ) / 6;
        mpa.clear() , mpb.clear();
        for ( int i = 1 ; i <= n ; i ++ ) a[i] = read() , b[i] = read() , mpa[a[i]] ++ , mpb[b[i]] ++;
        for ( int i = 1 ; i <= n ; i ++ ) ans -= ( mpa[a[i]] - 1 ) * ( mpb[b[i]] - 1 );
        cout << ans << endl;
    }
}

Staircases

我们设 \(f_{i,j,0/1}\) 表示到 \((i,j)\) 点,当前格子作为右上/左下拐点的方案数。

初始化 \(f_{i,j,0}=f_{i,j,1}=1\)

那么我们首先将全部为 \(0\) 的情况的答案先算出来,即:\(f_{i,j,0}\leftarrow f_{i-1,j,1},f_{i,j,1}\leftarrow f_{i,j-1,0}\)

\(ans=\sum_{i=1}^n\sum_{j=1}^m f_{i,j,0}+f_{i,j,1}-1\)

考虑一个修改 \((x,y)\) 的贡献,所有经过这个点的合法楼梯,那么我们向四个方向搜索并组合,累计修改即可。

注意当 \((x,y)\) 点不合法的时候,我们是不能直接 \(break\) 的。

参考了这篇代码的书写方式,使修改操作更加简洁。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define inl inline
#define getchar() cin.get()
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
const int N = 1000 + 5;

int read()
{
	int f = 1 , x = 0;
	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 , ans , f[N][N][2] , a[N][N] , cnt[4];//(i,j),作为右上或左下拐点。

vector<pii> d[4] = { vector<pii> { {0,1},{1,0} } , vector<pii> { {1,0},{0,1} } , vector<pii> { {0,-1},{-1,0} } , vector<pii> { {-1,0},{0,-1} } };

int check ( int x , int y ) { return 1 <= x && x <= n && 1 <= y && y <= m ; }

signed main ()
{
	ios::sync_with_stdio(false);
	cin.tie(0) , cout.tie(0);
    n = read() , m = read() , q = read();
    for ( int i = 1 ; i <= n ; i ++ )
        for ( int j = 1 ; j <= m ; j ++ )
            f[i][j][0] = f[i][j][1] = 1 , f[i][j][0] += f[i-1][j][1] , f[i][j][1] += f[i][j-1][0] , ans += f[i][j][0] + f[i][j][1] - 1;
    for ( int i = 1 ; i <= q ; i ++ )
    {
        int x = read() , y = read();
        fill ( cnt , cnt + 4 , 0 );
        for ( int i = 0 ; i < 4 ; i ++ )
        {
        	int op = 0 , tx = x , ty = y;
        	while ( check(tx,ty) && ( !a[tx][ty] || tx == x && ty == y ) ) ++ cnt[i] , tx += d[i][op].fi , ty += d[i][op].se , op ^= 1;
        }
        ans += ( a[x][y] == 1 ? 1 : -1 ) * ( cnt[0] * cnt[3] + cnt[1] * cnt[2] - 1 );
        a[x][y] ^= 1;
        cout << ans << endl;
    }
    return 0;
}   

posted @ 2023-11-10 17:46  Echo_Long  阅读(7)  评论(0编辑  收藏  举报