Two LIS Sum
结论是,其中一个序列的
L
I
S
LIS
LIS一定是
n
n
n。这结论为啥我还想了半天啊
Avoid Prime Sum
简单构造题。分 n n n的奇偶性讨论,上半部分全填奇数,下半部分全填偶数,中间对于奇偶数的分界线,可以考虑填 i i i和 2 i 2i 2i。
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
using namespace std;
int n,a[1005][1005],vis[1000005];
vector<int>v1,v2,v3,v4;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
if(n==3){
cout<<"1 3 5\n8 6 9\n4 2 7";
return 0;
}
if(n==4){
cout<<"15 11 16 12\n13 3 6 9\n14 7 8 1\n4 2 10 5";
return 0;
}
if(n%2==0){
for(int i=1;i<=n;i++){
a[n/2][i]=i*2+1;
a[n/2+1][i]=i*4+2;
vis[i*2+1]=vis[i*4+2]=1;
}
for(int i=1;i<=n*n;i++){
if(!vis[i]){
if(i%2)v1.pb(i);
else v2.pb(i);
}
}for(int i=1;i<n/2;i++){
for(int j=1;j<=n;j++){
a[i][j]=v1.back();v1.pop_back();
}
}
for(int i=n/2+2;i<=n;i++){
for(int j=1;j<=n;j++){
a[i][j]=v2.back();v2.pop_back();
}
}
}
else {
a[n/2+1][n/2+1]=9,a[n/2][n/2]=3;
a[n/2+1][n/2]=6,a[n/2+2][n/2+1]=18;
vis[9]=vis[3]=vis[6]=vis[18]=1;
for(int i=1;i<=n;i++){
if(!vis[i*2+1])v3.pb(i*2+1),vis[i*2+1]=vis[i*4+2]=1;
}
for(int i=1;i<n/2;i++){
a[n/2][i]=v3.back(),a[n/2+1][i]=v3.back()*2;v3.pop_back();
}
for(int i=n/2+2;i<=n;i++){
a[n/2+1][i]=v3.back(),a[n/2+2][i]=v3.back()*2;v3.pop_back();
}
for(int i=1;i<=n*n;i++){
if(!vis[i]){
if(i%2)v1.pb(i);
else v2.pb(i);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(!a[i][j]){
if(i<=n/2)a[i][j]=v1.back(),v1.pop_back();
else a[i][j]=v2.back(),v2.pop_back();
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[i][j]<<' ';
}cout<<endl;
}
}
Simultaneous Sugoroku
考场上根本没时间想。。。
对于起点是 1 ∼ 1 0 6 1\sim 10^6 1∼106的每个点,如果当前 x > 0 x>0 x>0那么往左走 d d d步,如果 x < 0 x<0 x<0那么往右走 d d d步,如果走到 0 0 0就停下来。
观察这个运动过程。如果某一时刻两个数移动到了 x x x和 − x -x −x的位置,那么接下来他们的移动都是对称的,也就是说是一对相关性的点。
所以只维护原点左侧或右侧的点即可。复杂度 O ( m + max ( w i ) ) O(m+\max(w_i)) O(m+max(wi))。
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
using namespace std;
int n,m,l=1,X[1000005],fa[1000005],res[1000005],mx[1000005];
deque<int>q;
void dfs(int x){
if(~mx[x])return;dfs(fa[x]);
if(mx[fa[x]])mx[x]=1,res[x]=res[fa[x]];
else mx[x]=0,res[x]=-res[fa[x]];
}
int main(){
cin>>n>>m;int tmp=0;for(int i=1;i<=n;i++)cin>>X[i],tmp=max(tmp,X[i]);memset(mx,-1,sizeof mx);
for(int i=1;i<=tmp;i++)q.push_back(i);
for(int i=1;i<=m;i++){
int d;cin>>d;if(l>0)l-=d;else l+=d;
int r=l+q.size()-1;
if(l<=0&&r>=0){
mx[q[abs(l)]]=1,res[q[abs(l)]]=i;
if(abs(l)<=abs(r)){
for(int j=0;j<abs(l);j++){
fa[q[j]]=q[2*abs(l)-j];
}for(int j=0;j<=abs(l);j++)q.pop_front();l=1;
}
else {
for(int j=0;j<abs(r);j++){
fa[q[q.size()-j-1]]=q[2*abs(l)-q.size()+j+1];
}for(int j=0;j<=abs(r);j++)q.pop_back();
}
}
}
for(int i=0;i<q.size();i++){
mx[q[i]]=0,res[q[i]]=l+i;
}
for(int i=1;i<=n;i++){
dfs(X[i]);if(mx[X[i]])cout<<"Yes"<<' '<<res[X[i]]<<endl;
else cout<<"No"<<' '<<res[X[i]]<<endl;
}
}
Sliding Window Sort
首先这个排序过程很不舒服
考虑将序列固定成每次只对前 m m m个数排序。每次排序完序列整体左移一位。
对于一个序列,我们可以把它看成两个部分,注意到前 m − 1 m-1 m−1个数始终有序,并且每次会把最小的那个数弹出到序列末尾,而后 n − m + 1 n-m+1 n−m+1个数始终在往前移位。
显然 K > n − m + 1 K>n-m+1 K>n−m+1过后左右两部分的集合就不会发生变化了。考虑从最终序列右一半入手,记作 { x i } \{x_i\} {xi}。记初始序列 { a i } ( b i ) \{a_i\}(b_i) {ai}(bi)。注意到如果 x i − 1 > x i x_{i-1}>x_i xi−1>xi那么 b i = x i b_i=x_i bi=xi。
注意到忽略上述确定的值后 { x i } \{x_i\} {xi}和 { b i } \{b_i\} {bi}均为递增,问题转述为每次排序的 m m m个数中都有最小值 b i b_i bi,那么合法的 { a i } ( b i ) \{a_i\}(b_i) {ai}(bi)数目为 m l e n × ( m − 1 ) ! m^{len}\times (m-1)! mlen×(m−1)!。
如果 K < n − m + 1 K<n-m+1 K<n−m+1那么把多余的数删掉即可。
复杂度 O ( n ) O(n) O(n)。
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
using namespace std;
const int mod=998244353;
int n,m,K,a[600005];
ll fpow(ll x,ll y){
ll z(1);
for(;y;y>>=1){
if(y&1)z=z*x%mod;
x=x*x%mod;
}return z;
}
int main(){
cin>>n>>m>>K;
for(int i=0;i<n;i++)cin>>a[i];
if(K<n-m+1)n-=n-m+1-K;for(int i=0;i<n;i++)a[i+n]=a[i];
vector<int>vec(a+K%n,a+K%n+n);K%=n-m+1;
vector<int>vec2=vec;sort(vec2.begin(),vec2.end());
for(auto &x:vec)x=lower_bound(vec2.begin(),vec2.end(),x)-vec2.begin()+1;
for(int i=0;i<m-1;i++){
if(vec[i]!=n-m+2+i){
cout<<0;return 0;
}
}
vec.erase(vec.begin(),vec.begin()+m-1);
for(int i=0;i<n-m+1;i++)vec.pb(vec[i]);
vector<int>vec3(vec.begin()+n-m+1-K,vec.begin()+n-m+1-K+n-m+1);
int len=n-m+1,x=vec3[0];
for(int i=1;i<vec3.size();i++){
if(vec3[i]<x)len--;
else x=vec3[i];
}
ll res=fpow(m,len);for(int i=1;i<=m-1;i++)res=res*i%mod;
cout<<res;
}
Rational Number System
咕咕咕。。。