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
題意:給一個字串,求任意一個子串使得本質不同子串數量為偶數。
注意到 aa
和 abc
的本質不同子串數都是偶數,而不存在這類子串的字串只有形如 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';
}