C题
现在给你n个数,让你找出1~n的一个排列,使得此排列与这n个数对应下标相等的每一个数的值都不相同,如果找到了就输出YES,并打印这个排列,找不到就输出NO。
一道比较简单的排序问题,但我写的不知道为什么会T,队友想法和我差不多,他却过了。(后面看出来了,我没有减少循环次数,所以会浪费很多运行时间)
#include <bits/stdc++.h>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int t,n,a[100005],m,ju,b[100005],k;
bool flag;
int main()
{
t=read();
for (int pp=1;pp<=t;pp++){
n=read();
a[1]=read();
ju=a[1];
flag=true;
for (int i=2;i<=n;i++){
a[i]=read();
if (a[i]!=ju && flag==true){
flag=false;
}
}
if (flag){
cout<<"NO"<<endl;
continue;
}
k=1;
memset(b,0,sizeof(b));
//cout<<"dddd"<<endl;
while(k<=n){
for (int i=1;i<=n;i++){
if (k!=a[i] && b[i]==0){
b[i]=k;
k++;
}
}
}
cout<<"YES"<<endl;
for (int i=1;i<=n;i++)
printf("%d ",b[i]);
cout<<endl;
}
return 0;
}
队友则是优化了许多地方(主要还是多了一步特判)。
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N],p[N];
int n;
void solve(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
bool flag=true;
for(int i=2;i<=n;i++) if(a[i]!=a[i-1]){
flag=false;
break;
}
vector<int> q;
if(flag){
puts("NO");
return ;
}
else{
for(int i=1;i<=n;i++) p[i]=i;
for(int i=1;i<=n;i++){
if(p[i]==a[i]) q.push_back(i);
}
int k=q.size();
if(k%2==0){
for(int i=0;i<k-1;i++){
swap(p[q[i]],p[q[i+1]]);
}
}
else{
for(int i=1;i<k-1;i++){
swap(p[q[i]],p[q[i+1]]);
}
for(int i=1;i<=n;i++){
if(q[0]!=i&&p[q[0]]!=a[i]&&p[i]!=a[q[0]]) {swap(p[q[0]],p[i]);break;}
}
}
puts("YES");
for(int i=1;i<=n;i++) cout<<p[i]<<" ";
cout<<endl;
}
}
int main()
{
int t;
cin>>t;
while(t--){
solve();
}
}
F题
给出一个长为n的数组,如果相邻两个数相等或者相加=x,那么就可以消除这两个数,剩下的数接在一起。求最多可以对原数组消除多少次。
就是拿双端队列,能消就消,维护一下即可。注意由于是环形,所以最后要把序列开头和结尾的能匹配的消掉。消除的先后顺序是没有区别的。
但我一直试着拿数组写,所以T了一发,后面改成队列就AC了,难度不大,但就是自己喜欢手模拟队列,真的难受。
#include<bits/stdc++.h>
using namespace std;
#define pr pair<ll,ll>
#define FLS fflush(stdout)
typedef long long ll;
void solve(){
int n, x, t;
cin >> n >> x;
list<int> lt;
for(int i = 0; i < n; i++){
cin >> t;
lt.push_back(t);
}
bool flag = true;
int ans = 0;
while(flag && lt.size() > 1){
flag = false;
auto it = lt.begin(), itt = it++;
do{
if(*it == *itt || *it+*itt == x){
lt.erase(it);
itt = lt.erase(itt);
it = itt--;
flag = true;
ans++;
}
else{ it++; itt++; }
if(it == lt.end()) it++;
if(itt == lt.end()) itt++;
}while(itt != lt.begin());
}
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T = 1;
// cin >> T;
while(T--) {
solve();
}
return 0;
}
G题
给出q个询问(1e5),每个询问给出一个长为2e5的字符串,判断用正则表达式去匹配最小的正则表达式长度,以及有多少种该长度的表达式可以匹配这个字符串。
一道让人看了头晕的题,但后面可以很直观的发现特点,“.*”可以匹配所有串,因此答案长度≤2,只需要对1和2分别讨论。所以也是一道签到题,不过题目的描述确实送走不少人。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int main(){
int q;
scanf("%d",&q);
while(q--){
char s[N];
scanf("%s",s);
int len=strlen(s);
if(len==1){
printf("1 2\n");
}
else if(len==2){
if(s[0]!=s[1])printf("2 6\n");
else printf("2 8\n");
}
else{
int i;
for(i=0;i<len-1;i++){
if(s[i]!=s[i+1])break;
}
if(i<len-1)printf("2 2\n");
else printf("2 4\n");
}
}
}
补题时间
J题
给出k(<64),构造一个长度为n(<64),每个数都属于[0,k-1]的数组,满足其中恰好有t个非空连续子序列的和是被k整除的,求最够能构造多少个这样的数组,答案模998244353。
看其他人题解用前缀和考虑0~𝑘−1中每个数的出现次数,对于每个出现次数x,𝐶(𝑥,2)一下就是答案,最后累加即为满足条件的子区间个数。大致看懂了大佬的代码,但还是不会写,就借用一下大佬代码。
#include<bits/stdc++.h>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int kmod=998244353;
const int kmaxn=70;
int n,k,t;
int dp[70][70][2500];
int c[70][70];
void ini(){
for (int i=0;i<kmaxn-2;i++)
c[i][0]=c[i][i]=1;
for (int i=1;i<kmaxn-2;i++)
for (int j=1;j<i;j++)
c[i][j]=((ll)c[i-1][j]+c[i-1][j-1])%kmod;
}
int main(){
scanf("%d%d%d",&n,&k,&t);
ini();
for(int len=0;len<=n;len++){
dp[0][len][c[len+1][2]]=c[n][len];
}
for(int i=1;i<k;i++){
for(int len=0;len<=n;len++){
for(int s=0;s<=t;s++){
if(!dp[i-1][len][s]) continue;
for(int num=0;num+len<=n;num++){
dp[i][len+num][s+c[num][2]]=(dp[i][len+num][s+c[num][2]]+(ll)dp[i-1][len][s]*c[n-len][num]%kmod)%kmod;
}
}
}
}
printf("%d\n",dp[k-1][n][t]%kmod);
return 0;
}
K题
类似于洛谷里面的移石子问题,设计到博弈论之类的算法,自己也没怎么看懂,不过在看了学长
Frank_Star的代码后有点灵感,但也不会写(还是太菜了我),不过大致的结论还是勉强懂了。