Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2)

A.

直接从最小的开始构造即可,最小的差值都不能满足最大的肯定也不能满足

#include
using namespace std;
const int N = 2e5+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n;
int a[N];
void solve(){
    int x,y;
    cin>>x>>y>>n;
    a[1]=x;
    a[n]=y;
    

        int now=1;
        for(int j=n-1;j>=1;j--)
        {
            a[j]=a[j+1]-now;
            now++;
        }    
        if(a[1]>=x)
        {
            a[1]=x;
            for(int j=1;j<=n;j++) cout<>t;
    while(t--) solve();
}

B.

分析性质:

第一个操作,可以让同奇偶的不同位置数任意交换

第二个操作,可以改变当前数的下标的奇偶性(k%2==0,可以改变),否则不能改变

如果可以任意改变直接排序即可否则

所以直接把不同下标的扣出来排序即可

#include
using namespace std;
const int N = 2e5+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n,k;
int a[N];
void solve(){
    cin>>n>>k;
    string s;
    cin>>s;
    if(k%2==0){
        sort(s.begin(),s.end());
        cout< b,c;
        for(int i=0;i>t;
    while(t--) solve();
}

C.

我们可以逆着操作且等价

我们先尽可能靠近n,每次加上自己,因为1*n=n,n是自己的因子

这个操作其实很像倍增,相当于每次加一个2^i

最后不能加了,我们考虑差值

先想想当前数有哪些因子,因为最终答案肯定是某一个2^i,所以他的因子肯定可以表示2^x*2^y(x,y<=i)

所以我们用二进制凑出这个差值即可

并且每个2^i最多用两次

#include
using namespace std;
const int N = 3010,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n,k;
int g[N][N];
void solve(){
    //线性dp
    cin>>n;
    int res=0;
    int x=1;
    vector a;
    while(x<=n)
    {
        a.push_back(x);
        if(x*2>n) break;
        x*=2;
    }
    int y=n-a.back();

    for(int i=60;i>=0;i--)
    {
        if(y>>i&1)
        { 
       
            a.push_back((a.back()+(1ll<>t;
    while(t--) solve();
}

D.首先因为操作当前(i,j),只会改变下面行的状态,所以直接从开头行枚举,有1就只能操作

然后用一个懒标记,标记数组变化

维护三个数组,因为改变的是以当前(i,j)为头的金字塔

所以维护一个斜左右下角,垂直向下,

#include 
using namespace std;
#define int long long
const  int N = 3010, inf = 0x3f3f3f3f3f;
int n;
char s[N][N];
void sovle() {
	cin>>n;
	for(int i=1;i<=n;i++){
	    for(int j=1;j<=n;j++)
	        cin>>s[i][j];
	}
	int res=0;
	vector> l(n+2,vector(n+2,0));
	vector> d(n+2,vector(n+2,0));
	vector> r(n+2,vector(n+2,0));
	vector> val(n+2,vector(n+2,0));
	
	for(int i=1;i<=n;i++){
	    for(int j=1;j<=n;j++){
	        if(l[i][j]){
	            val[i][j]^=1;
	            l[i+1][j-1]^=1;
	            d[i+1][j]^=1;
	        }
	        if(d[i][j]){
	            val[i][j]^=1;
	            d[i+1][j]^=1;
	        }
	        if(r[i][j]){
	            val[i][j]^=1;
	            r[i+1][j+1]^=1;
	            d[i+1][j]^=1;
	        }
	        int num=s[i][j]-'0';
	        if(num^val[i][j])
	        {
	            res++;
	            l[i+1][j-1]^=1;
	            d[i+1][j]^=1;
	            r[i+1][j+1]^=1;
	        }
	    }
	}
	cout<> t;
	while (t--) {
		sovle();
	}
}

E:

首先手玩一下

a,b ,c=a|b

第一轮:如果a最高位的1和c最高位不等于 可以判断 a 第二轮:如果a最高位的1和c最高位不等于 || b的次高位不等于c的次高位(因为第一轮可以得出最高位的a一定是1) 可以判断
第三轮:(由前两轮得出最高位得1和次高位的1,b都有)(可以得到b的最高位1跟a的1一样)如果a的次高位不等于c的次高位 || a的第三位1不等于c的第三位1

.....

可以观察得出只能1的个数有关,所以我们直接用01trie,去dfs一遍边算边计算贡献

要记录当前点前面有多少个1

然后计算轮数的时候,如果tr[u][0]&&tr[u][1]当前此高位能分出01

那么贡献是当前数的个数*两个人的轮数(因为当前可能是到第一个人操作也可能是第二个人操作,因为给第一个a的数,给二个人b的数,可以反过来,因为题目选的数随机)

如果最后没有就证明a=b,直接结束即可,那么贡献就是全部1的个数了

#include
using namespace std;
const int N = 2e5+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;
int tr[N*32][2],tot,len[N*32],cnt[N*32],ans;
int qmi(int a, int k, int p)  // 求a^k mod p
{
    int res = 1 % p;
    while (k)
    {
        if (k & 1) res = (LL)res * a % p;
        a = (LL)a * a % p;
        k >>= 1;
    }
    return res;
}
void dfs(int u){
    if(!tr[u][0]&&!tr[u][1]){
        ans=(ans+1ll*cnt[u]*cnt[u]%mod*(len[u]+1)%mod)%mod;
        return ;
    }
    if(tr[u][0]&&tr[u][1])//次高位
    {
        int lef=cnt[tr[u][0]],rig=cnt[tr[u][1]];
        int x=len[u]+1,y=len[u]+2;
        ans=(ans+1ll*lef*rig%mod*(x+y)%mod)%mod;
    }
    if(tr[u][0])dfs(tr[u][0]);
    if(tr[u][1])dfs(tr[u][1]);
}
void solve(){
    tot=0,ans=0;
    cin>>n;
    for(int i=1,x;i<=n;i++){
        cin>>x;
        int p=0;
        for(int j=30;j>=0;j--){
            int c=x>>j&1;
            if(!tr[p][c]) 
            tr[p][c]=++tot,len[tot]=len[p]+(c==1);
            p=tr[p][c];
            cnt[p]++;
        }
    }
    dfs(0);
    ans=1ll*ans*qmi(n*n%mod,mod-2,mod)%mod;
    cout<>t;
    while(t--) solve();
}

F.

首先手玩样例,最少操作次数肯定是区间不同数的个数(cnt数组就是处理这个的,前缀和),根据贪心我们尽可能选择连续的区间操作

2 3 2 6 3 10 1 2

对于l,r=2,3

3 2 6 3这个区间,把6去掉看成 

3 2 3,这个2是把无法避免要把两个3分开操作的,否则就变成-1了,

对于相同数的两个位置=x,y

如果[x+1,y-1]中有一个数mx满足 mx>=l&& mx

所以对于这个操作我们需要离线处理,每次固定一个右端点,然后找到当前[x+1,y-1]

区间中,最大的满足

然后考虑计算贡献,先不考虑 l 的位置,如果满足区间中,最大的满足

这个数需要给[1,r],[2,r],[3,r].....[mx,r]这些不同的 l 都需要加上一个代价1,所以我们直接把[1,mx]的区间去增加一个1,最后答案就是不同数的个数加上当前bit【l】的值了,这里用的是树状数组

把区间[1,mx]都加一,用了差分处理的,最后求当前l的值就是他的前缀和,一开始差分数组都是0

所以初始化树状数组不用特别处理

#include
using namespace std;
const int N = 2e6+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;
int a[N];
vector pos[N];
vector query[N]; 
int ans[N];

template
struct Fenwick{
    int n;
    vector tr;

    Fenwick(int n) : n(n), tr(n + 1, 0){}

    int lowbit(int x){
        return x & -x;
    }

    void modify(int x, T c){
        for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
    }

    void modify(int l, int r, T c){
        modify(l, c);
        if (r + 1 <= n) modify(r + 1, -c);
    }

    T query(int x){
        T res = T();
        for(int i = x; i; i -= lowbit(i)) res += tr[i];
        return res;
    }

    T query(int l, int r){
        return query(r) - query(l - 1);
    }

    int find_first(T sum){
        int ans = 0; T val = 0;
        for(int i = __lg(n); i >= 0; i--){
            if ((ans | (1 << i)) <= n && val + tr[ans | (1 << i)] < sum){
                ans |= 1 << i;
                val += tr[ans | (1 << i)];
            }
        }
        return ans + 1;
    }

    int find_last(T sum){
        int ans = 0; T val = 0;
        for(int i = __lg(n); i >= 0; i--){
            if ((ans | (1 << i)) <= n && val + tr[ans | (1 << i)] <= sum){
                ans |= 1 << i;
                val += tr[ans | (1 << i)];
            }
        }
        return ans;
    }

};
using BIT = Fenwick;

struct Info {
    int mx = 0;
};

Info operator+(const Info &a, const Info &b){
    return {max(a.mx, b.mx)};
}

template
struct SegmentTree{
    int n;
    vector info;

    SegmentTree() {}

    SegmentTree(int n, Info _init = Info()){
        init(vector(n, _init));
    }

    SegmentTree(const vector &_init){
        init(_init);
    }

    void init(const vector &_init){
        n = (int)_init.size();
        info.assign((n << 2) + 1, Info());
        function build = [&](int p, int l, int r){
            if (l == r){
                info[p] = _init[l - 1];
                return;
            }
            int m = (l + r) / 2;
            build(2 * p, l, m);
            build(2 * p + 1, m + 1, r);
            pull(p);
        };
        build(1, 1, n);
    }

    void pull(int p){
        info[p] = info[2 * p] + info[2 * p + 1];
    }

    void modify(int p, int l, int r, int x, const Info &v){
        if (l == r){
            info[p] = v;
            return;
        }
        int m = (l + r) / 2;
        if (x <= m){
            modify(2 * p, l, m, x, v);
        } 
        else{
            modify(2 * p + 1, m + 1, r, x, v);
        }
        pull(p);
    }

    void modify(int p, const Info &v){
        modify(1, 1, n, p, v);
    }

    Info query(int p, int l, int r, int x, int y){
        if (l > y || r < x){
            return Info();
        }
        if (l >= x && r <= y){
            return info[p];
        }
        int m = (l + r) / 2;
        return query(2 * p, l, m, x, y) + query(2 * p + 1, m + 1, r, x, y);
    }

    Info query(int l, int r){
        return query(1, 1, n, l, r);
    }
};
void solve(){
   cin>>n>>m;
   for(int i=1;i<=n;i++){
       cin>>a[i];
       pos[a[i]].push_back(i);
   }
   for(int i=0;i>l>>r;
       query[r].emplace_back(l,i);
   }
   BIT bit(n);
   SegmentTree seg(n);
   vector cnt(n+1);
   for(int i=1;i<=n;i++){
       cnt[i]=cnt[i-1];
       if(!pos[i].empty()){
           cnt[i]++;
           seg.modify(pos[i][0],{i});
           for(int j=1;j>t;
    while(t--) solve();
}

你可能感兴趣的:(算法,codeforce)