A.Dreamoon and Ranking Collection
题意:
给n个数,是否存在一个1−v的序列
其中如果某个数不存在,可以跳过x次
找出最大的v
题解:
用数组存一下每个数的个数
从1−200循环,如果数存在就下一个,不存在就跳过
直到x==0 && 当前数不存在
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int a[210],b[210];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--){
int n,x,ans=0;
cin>>n>>x;
memset(b,0,sizeof b);
for(int i=1;i<=n;i++)cin>>a[i],b[a[i]]=1;
for(int i=1;i<=200;i++){
if(!b[i]&&!x)break;
if(!b[i])x--;
ans=i;
}
cout<<ans<<endl;
}
}
B.Dreamoon Likes Permutations
题意:
给一个长度为n的数组
是否能分成左右两部分,使得每部分成为一个序列
即包含1−x的所有数
题解:
直接计算前缀和和后缀和
用一个map存一下是否出现重复元素,出现就break
否则用高斯公式算如果前缀和和后缀和都满足则记录答案
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int a[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--){
int n;
vector<int> ans;
map<int,int> m1,m2;
cin>>n;
int num=0;
ll pre=0,sum=0;
for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i],m2[a[i]]++;
for(ll i=1;i<n;i++){
pre+=a[i];
m1[a[i]]++;
if(m1[a[i]]>1) break;
m2[a[i]]--;
if(m2[a[i]]==0) m2.erase(a[i]);
if(m1.size()+m2.size()==n&&pre==(1+i)*i/2&&(sum-pre)==(1+n-i)*(n-i)/2) ans.pb(i),num++;
}
cout<<ans.size()<<endl;
for(auto i:ans){
cout<<i<<' '<<n-i<<endl;
}
}
}
C.Dreamoon Likes Coloring
题意:
n个点,涂色m次,每次涂的长度为Li,颜色为i
你选定的涂色位置必须保证整个长度都能够涂上该颜色
每个点的颜色取决于最后一次涂的颜色
确保每个颜色都存在并且每个点都有颜色
题解:
特判一下颜色不覆盖,如果不够n个点,输出−1
然后如果还没涂的长度能够大于没涂的点,就在上次涂后的下一个点涂
如果这样涂超出了n个点,就输出−1
如果剩余还没涂的长度小于剩下的点,就在n−sumi+1位置开始涂
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
ll l[maxn],sum[maxn],ans[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)cin>>l[i];
for(int i=m;i;--i)
sum[i]=sum[i+1]+l[i];
if(sum[1]<n){cout<<-1;return 0;}
ans[1]=1;
for(int i=2;i<=m;++i)
ans[i]=max(ans[i-1]+1,n-sum[i]+1);
for(int i=1;i<=m;++i)if(ans[i]+l[i]-1>n){cout<<-1;return 0;}
for(int i=1;i<=m;++i)
cout<<ans[i]<<' ';
return 0;
}
D.Dreamoon Likes Sequences
题意:
给一个数d和m,m是模数,最后答案向m取余
让你构造一个数组1<=a1<a2<....an<=d
必须存在数组b是a的异或前缀,保证b也是严格升序
题解:
可以看出,如果b也是严格升序的话
必须让a的每一位数的二进制最高位大于前一位的最高位
所以就对每一二进制位循环
i从0开始,假设最高位是1<<i,存在2i种数
所以每次用前面的所有情况乘这个数的种类数
并且加上这个数单独存在的情况,然后加上前面所有出现的情况
这样就构造出了一个O(log2d)复杂度的dp操作
由于每次操作只和前一个有关,所以只用一个数一直维护就可以
AC代码
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t;
cin>>t;
while(t--){
ll d,m;
cin>>d>>m;
ll ans=0;
for(int i=0;(1ll<<i)<=d;i++){
int s=0;
if((1ll<<(i+1))<=d)s=1<<i;
else s=d-(1<<i)+1;
ans=(ans+s*ans%m+s)%m;
}
cout<<ans<<endl;
}
return 0;
}