A。傻逼題
#include<bits/stdc++.h>
#define MAXN 405
using namespace std;
int T,n,a[MAXN],judge[MAXN],x;
int main(){
cin>>T;
while(T--){
cin>>n>>x;memset(judge , -1 , sizeof(judge));
for(int i = 1 ; i <= n ; i++){cin>>a[i];judge[a[i]] = 1; }
for(int i = 1 ; i <= 400 ; i++){
if(judge[i] == (-1) && x == 0){cout<< i - 1 <<endl;break;}
if(judge[i] == (-1))x--;
}
}
}
B。給你一串數字,問你這串數字能分成兩段,且兩端是個1—n的排列的方案數,並且輸出方案
顯然:一個段能是一個1—n的排列,只有當它的最大值等於這段內的不同的元素個數
那麼很顯然,可以根據這個從左往右掃,在反向掃一遍即可
#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
int T,n,a[MAXN],judge[MAXN],ok[MAXN],ok2[MAXN],sum,ans,maxl1[MAXN],maxl2[MAXN];
int main(){
cin>>T;
while(T--){
cin>>n;
for(int i = 1 ; i <= n ; i++)cin>>a[i];
for(int i = 1 ; i <= n ; i++)judge[a[i]] = ok[i] = ok2[i] = (-1);
sum = maxl1[0] = maxl2[n + 1] = 0;
for(int i = 1 ; i <= n ; i++){
if(judge[a[i]] == (-1)){
judge[a[i]] = 1;
maxl1[i] = max(maxl1[i - 1] , a[i]);
sum++;
if(sum == maxl1[i])ok[i] = 1;
}
else break;
}
sum = 0;
for(int i = n ; i >= 1 ; i--){
if(judge[a[i]] == (-1) || judge[a[i]] == 1){
judge[a[i]] = 2;
maxl2[i] = max(maxl2[i + 1] , a[i]);
sum++;
if(sum == maxl2[i])ok2[i] = 1;
}
else break;
}
ans = 0;
for(int i = 1 ; i < n ; i++){
if(ok[i] == 1 && ok2[i + 1] == 1){
ans++;
}
}
cout<<ans<<endl;
for(int i = 1 ; i < n ; i++){
if(ok[i] == 1 && ok2[i + 1] == 1){
cout<<maxl1[i]<<" "<<maxl2[i + 1]<<endl;
}
}
}
}
C,有m次操作,每次可以覆蓋一段長度爲Li的區間,讓你輸出一個方案使得1—n都被覆蓋,且每種顏色都出現
一個很顯然的判定不合法的條件,長度和<n
對於無解判斷,只要對於每種顏色,前面儘量少放,然後還是放不下,就無解
可以考慮每次只給每種顏色留一個空格,然後每次讓每一個顏色儘量往後面覆蓋即可
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
long long n,m,sum,len[MAXN],ans[MAXN],maxl;
void init(){
cin>>n>>m; sum = maxl = 0;
for(int i = 1 ; i <= m ; i++){
cin>>len[i];
sum += len[i];
}
if(sum < n){cout<<-1<<endl;exit(0);}
for(int i = 1 ; i <= m ; i++){
if(n < (i + len[i] - 1)){
cout<<-1<<endl;
exit(0);
}
}
for(int i = 1 ; i <= m ; i++)ans[i] = i;
maxl = n;
for(int i = m ; i >= 1 ; i--){
if(i + len[i] - 1 <= maxl)ans[i] = maxl - len[i] + 1 , maxl = maxl - len[i];
else break;
}
for(int i = 1 ; i <= m ; i++){
cout<<ans[i]<<" ";
}
}
int main(){
init();
}
D.給你一個d,問你 構造一個遞增序列 最後一項小於等於d,並且他們的異或前綴和序列也是遞增的方案數
打表發現
於是乎,可以把每次分個組
(1),(2,3),(4,5,6,7),(8,9,10,11,12,13,14,15)。。。然後每組選一個就好了
注意邊界
#include<bits/stdc++.h>
using namespace std;
int T;
long long m,d,f[105],s,tot,b[105],g;
int main(){
cin>>T;g = 0;
while(T--){
cin>>d>>m;
s = 1;
tot = 0;
while(s <= d){
tot++;
b[tot] = min(d - s + 1 , s);
s = s << 1;
}
for(int i = 1 ; i <= tot ; i++){
f[i] = (f[i - 1] * b[i]) % m+ (f[i - 1]) % m + b[i] % m;
}
cout<<max(f[tot] % m , g)<<endl;
}
}