2024.11.23 CodeTON Round 9 (Div. 1 + Div. 2)

EssnSlaryt發表於2024-11-24

Solved:6/11

Rank:136


感覺 F 差一步就做出來了。。。


A. Shohag Loves Mod

題意:給 \(n\),構造一個遞增序列使得 \(\{a_i\mod i\}\) 兩兩不同。

\(\{2i-1\}\)

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

void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;++i)cout<<i*2-1<<' ';
    cout<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

B. Shohag Loves Strings

題意:給一個字串,求任意一個子串使得本質不同子串數量為偶數。

注意到 aaabc 的本質不同子串數都是偶數,而不存在這類子串的字串只有形如 abababab...,其所有子串的本質不同子串數均為奇數。

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

void solve(){
    string a;
    cin>>a;
    int n=a.length();
    for(int i=0;i<n-1;++i)if(a[i]==a[i+1]){cout<<a[i]<<a[i+1]<<'\n';return;}
    bool fl=0;
    for(int i=2;i<n;++i)if(a[i]!=a[i&1])fl=1;
    if(!fl){cout<<"-1\n";return;}
    for(int i=0;i<n-2;++i)if(a[i]!=a[i+1]&&a[i]!=a[i+2]&&a[i+1]!=a[i+2]){cout<<a[i]<<a[i+1]<<a[i+2]<<'\n';return;}
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

C1. Shohag Loves XOR (Easy Version)

題意:給定 \(x,n\),求 \(1\leq y\leq n\) 中有多少個 \(y\) 滿足 \((x\oplus y)|x\)\((x\oplus y)|y\)\(x\leq 10^6, n\leq 10^{18}\)

\(y\) 的二進位制最高位比 \(x\) 高時,一定有 \(x\oplus y > x\)\(x\oplus y > \frac y2\)。此時不可能存在整除關係。因此直接從 \(1\)\(\min(n,2^k-1)\) 列舉 \(y\) 即可。這裡 \(2^k\)\(2\) 大於 \(x\) 的最小冪次。

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

void solve(){
    int x;
    ll n;
    cin>>x>>n;
    int m=1;
    while(m<=x)m<<=1;
    m=min((ll)m,n);
    int cnt=0;
    for(int i=1;i<=m;++i)if(i!=x){
        if(!(x%(x^i))||!(i%(x^i)))++cnt;
    }
    cout<<cnt<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

C2. Shohag Loves XOR (Hard Version)

題意:給定 \(x,n\),求 \(1\leq y\leq n\) 中有多少個 \(y\) 滿足 \(x|(x\oplus y)\)\(y|(x\oplus y)\)\(x\leq 10^6, n\leq 10^{18}\)

和 C1 類似,當 \(y\) 的二進位制最高位比 \(x\) 高時,\(x\oplus y\) 不可能是 \(y\) 的倍數,只可能是 \(x\) 的倍數。問題轉化為統計有多少 \(q\) 滿足 \(qx\oplus x\leq n\)。當 \(qx\)\(n\)\(k\) 位之前不相等時,\(qx\leq n\) 就等價於 \(qx\oplus x\leq n\),可以直接計算;故只需統計 \(qx\oplus x\)\(n\)\(k\) 位之前相等的情況,這部分可以暴力列舉;另外 \(y\) 很小的部分也可以暴力列舉(注意要減掉重複的)。

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

void solve(){
    int x;
    ll n;
    cin>>x>>n;
    int m=1;
    while(m<=x)m<<=1;
    if(m>=n){
        ll cnt=0;
        for(int i=1;i<=n;++i){
            if(!((x^i)%i)||!((x^i)%x))++cnt;
        }
        cout<<cnt<<'\n';
        return;
    }
    ll cnt=0;
    for(int i=1;i<m;++i){
        if(!((x^i)%i)&&(x^i)%x)++cnt;
    }
    ll l=n^(n&(m-1)),r=l+m;
    cnt+=(l-1)/x;
    for(ll y=(l-1)/x*x+x;y<r;y+=x){
        if((x^y)<=n)++cnt;
    }
    cout<<cnt<<'\n';
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

D. Shohag Loves GCD

題意:給定 \(n\) 和一個大小為 \(m\) 的集合 \(S\),構造一個序列,滿足序列中所有數都屬於 \(S\)\(\gcd(a_i,a_j)\neq a_{\gcd(i,j)}, \forall i\neq j\)

設整數 \(x\) 的質因子數量(計重數)為 \(f(x)\)。當 \(m\leq M=\max_{i=1}^n f(i)\) 時,滿足題意的序列一定不存在。

證明:此時一定存在下標序列 \(p_0,p_1,\dots p_M\) 使得 \(p_0|p_1|\dots |p_M\)。根據抽屜原理,一定有兩個 \(p_i,p_j\) 滿足 \(a_{p_i}=a_{p_j}\),而 \(\gcd(p_i,p_j)=p_i, \gcd(a_{p_i},a_{p_j}) = a_{p_i}\),不合題意。

而另一方面,當 \(m>M\) 時,我們只需將 \(S\) 從大到小排序並令 \(a_i = s_{f(i)}\) 即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()

const int N=1e5+5;
bool np[N];
int pri[N],cnt,f[N],mx[N];
void sieve(int n){
    for(int i=2;i<=n;++i){
        if(!np[i])pri[++cnt]=i,f[i]=1;
        for(int j=1;j<=cnt&&i*pri[j]<=n;++j){
            np[i*pri[j]]=1;
            f[i*pri[j]]=f[i]+1;
            if(!(i%pri[j]))break;
        }
    }
    for(int i=1;i<=n;++i)mx[i]=max(f[i],mx[i-1]);
}

void solve(){
    int n,m;
    cin>>n>>m;
    vector<int> a(m);
    for(int i=0;i<m;++i)cin>>a[i];
    if(m<=mx[n]){cout<<"-1\n";return;}
    sort(all(a)),reverse(all(a));
    for(int i=1;i<=n;++i)cout<<a[f[i]]<<' ';
    cout<<'\n';
}

int main(){
    sieve(1e5);
    ios::sync_with_stdio(0);cin.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}

E. Shohag Loves Inversions

題意:初始序列為 \([0,1]\),每次可將當前序列的逆序對數插入任意一個位置,求最終能生成的長度為 \(n\) 的序列的數量。對 \(998244353\) 取模。

插入一個數字在絕大多數情況下都會使序列的逆序對數增加。事實上,除了前幾次操作插入 \(0,1\) 外,只要序列的逆序對數 \(\geq 2\),那麼除非插在序列末尾,插在其他任何位置都會使逆序對數增加。

\(f_n\) 為:除末尾相同的和下次插入相等的數外,長度為 \(n+1\),且序列逆序對數 \(\geq 2\) 的方案數。邊界為 \(f_1=f_2=0, f_3=2\)。對新插入的數字分三種情況討論:

  • 新的數字是 \(1\) 且插入在前面:手玩可知逆序對數為 \(1\) 的序列只能形如 \(00...01011...1\),能構成的新序列總數為 \(2+3+\dots+(n-1)+n=\frac{(n-1)(n+2)}2\)

  • 新的數字 \(\geq 2\) 且插入在前面:由於此時末尾的數都不再是和下次插入相等的數,所以要考慮前面有 \(3\)\(n-1\) 個數的情形,方案總數為 \(\sum_{i=3}^{n-1} (i+1)f_i\)

  • 新的數字 \(\geq 2\) 且插入在末尾:沒有貢獻。

因此 \(f_n = \frac{(n-1)(n+2)}2 + \sum_{i=3}^{n-1} (i+1)f_i\),答案為 \(n-1+\sum_{i=3}^{n-1} f_i\)\(n\) 是逆序對數 \(\leq 1\) 的方案數)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define all(x) (x).begin(),(x).end()

const int N=1e6+5,mod=998244353;

int n=1e6;
ll f[N];

int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    f[1]=0,f[2]=0,f[3]=2;
    ll sum=8;
    for(int i=4;i<=n;++i){
        f[i]=(1ll*(i-2)*(i+1)/2+sum)%mod;
        sum=(sum+f[i]*(i+1))%mod;
    }
    for(int i=4;i<=n;++i)f[i]=(f[i]+f[i-1])%mod;

    int T;
    cin>>T;
    while(T--)cin>>n,cout<<(n-1+f[n-1])%mod<<'\n';
}

相關文章