自闭场,d题fst了,掉大分^^
A 题意
如果数字x的各个位数加和比x+1的大,称为一个特殊数字,问给出n,小于等于n的特殊数字个数
A 思路
这能wa1,我真服了。。显然只有9,19,29,等等尾巴是9的可以,那么答案就是(n+1)/10。代码实现和我嘴的思路不一样,不过签到题懒得改了。
A 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k;
void YES(){
cout<<"YES"<<endl;
}
void NO(){
cout<<"NO"<<endl;
}
void solve(){
string s;
cin>>s;
if(s.size()==1){
if(s=="9") cout<<1<<endl;
else cout<<0<<endl;
}
else{
int ans=0;
for(int i=0;i<s.size()-1;i++){
ans*=10;
ans+=s[i]-'0';
}
if(s[s.size()-1]=='9') ans++;
cout<<ans<<endl;
}
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>tn;
while(tn--){
solve();
}
}
B 题意
给你串a和b,你开始时选一个a的字符,只有向右移动若干次,再向左移动若干次,把所有接触到的字符都记录下来,问是否可以获得b
B 思路
长度小于500,暴力枚举就行了
B 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k;
void YES(){
cout<<"YES"<<endl;
}
void NO(){
cout<<"NO"<<endl;
}
void solve(){
string a,b;
cin>>a>>b;
n=a.size(),m=b.size();
a='z'+a;
for(int i=1;i<=n;i++){
for(int len=0;len<=m;len++){
string t;
t+=a[i];
for(int j=i+1;j-i<=len;j++){
t+=a[j];
}
for(int j=i+len-1,tmp=0;tmp<m-1-len&&j;j--,tmp++){
t+=a[j];
}
if(t==b){
YES();
return ;
}
}
}
NO();
return ;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>tn;
while(tn--){
solve();
}
}
C 题意
两队挨个踢球,1表示进了0没进?都有机会。如果某次踢完球后胜负已分(比如a全进b全不进a都要输),就终止,一共十轮,问最早可能结束的轮次。
C 思路
2^10=1024,直接dfs
C 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k;
void YES(){
cout<<"YES"<<endl;
}
void NO(){
cout<<"NO"<<endl;
}
string s;
int ans;
map<int,int>last;
void dfs(int x,int a,int b){
if(x>10) return ;
int lasta=last[x],lastb=10-x+1-lasta;
if(lasta+a<b||lastb+b<a){
ans=min(ans,x-1);
return ;
}
int who=x%2;//1 先手
if(s[x]=='1'){
if(who)
dfs(x+1,a+1,b);
else
dfs(x+1,a,b+1);
}
else if(s[x]=='0'){
dfs(x+1,a,b);
}
else{
if(who)
dfs(x+1,a+1,b);
else
dfs(x+1,a,b+1);
dfs(x+1,a,b);
}
}
void solve(){
cin>>s;
s='z'+s;
ans=10;
dfs(1,0,0);
cout<<ans<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>tn;
last[1]=5;
last[2]=4;
last[3]=4;
last[4]=3;
last[5]=3;
last[6]=2;
last[7]=2;
last[8]=1;
last[9]=1;
last[10]=0;
while(tn--){
solve();
}
}
D 题意
给你一个串,遍历他,你可以做以下操作
- 写下这个字符
- 不写这个字符,并且删除上一个
是否能得到另一个串?
D 思路
想复杂了。我的思路是这样一来,相当于让新串每一个字符找到一个匹配位置,满足这个对应的位置单增,且匹配位置下标相减为奇数。于是按奇偶性把原串拆了,在两个新串里搞双指针,成功fst了。原因是没考虑最后匹配掉后必须删完。再加条件时发现过于麻烦了,遂放弃。
学习脱老师解法,显然知道我们最后删完的话,最后一个匹配位置后面字符应当为偶数个,前面则没有限制。于是我们reverse字符串,从后向前搞,如果匹配到了,就去找下一个,否则下标加2,因为需要删掉这个没匹配字符。
D 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k;
void YES(){
cout<<"YES"<<endl;
}
void NO(){
cout<<"NO"<<endl;
}
void solve(){
string a,b,t;
cin>>a>>b;
n=a.size(),m=b.size();
if(n<m){
NO();
return ;
}
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
int i=0,j=0;
for(;j<m;j++){
while(i<n&&a[i]!=b[j])i+=2;
if(i>=n){
NO();
return ;
}
i++;
}
YES();
return ;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>tn;
while(tn--){
solve();
}
}
E 题意
一个排列1234567…n,我们定义k轮换为把最后k个放到前面来,也就是n-k+1,n-k+2…n,1,2,3,4,5…n-k。然后我们至多了两两交换m次,给出你操作后数组,问有几个k可能导致这种情况。
E 思路
前置知识,我们考虑012345…n-1这种排列
- 我们能发现,k轮换后的元素ai=(i-k)mod k,我们可以根据现在的ai倒推出k。当然,没发现前面那个mod关系也无所谓,也是可以倒退的。
- 一个well known的知识,交换多少次数字可以使元素有序,如果是相邻,是逆序对数,如果是任意,那么i向离散化的ai连边,答案是n-联通块数。
首先,我们给出一个k,可以利用第二点测算他能否由小于等于m次交换操作形成最终结果,复杂度O(n)。题目中的m最大为n/3,假设我们最优化m操作,也只能使2n/3个数字和原来的位置不一样,那么也就是说,我们可以预处理每一个数字假如在轮换后就没动过,他的轮换次数k是几。我们记录一下每个k出现了几次,只有某个k出现次数大于n/3的情况下,他才有机会成为答案,显然这样的k最多有三个,我们对这样的k单独判断一下即可。复杂度O(n)
E 代码
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<unordered_map>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<chrono>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=400505;
const int inf=0x3f3f3f3f;
int n,m,k;
int a[maxn];
int b[maxn];
void YES(){
cout<<"YES"<<endl;
}
void NO(){
cout<<"NO"<<endl;
}
map<int,int>mp;
vector<int>ans;
int fa[maxn];
int find(int x){
return x==fa[x]?fa[x]:fa[x]=find(fa[x]);
}
bool judge(int x){
int cnt=n;
for(int i=1;i<=n;i++){
int t=(i-1-x+n)%n+1;
// cout<<t<<' ';
if(a[i]!=t){
if(find(a[i])!=find(t)){
fa[find(a[i])]=find(t);
cnt--;
}
}
}
//cout<<endl;
return n-cnt<=m;
}
void solve(){
mp.clear();
cin>>n>>m;
ans.clear();
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=(i-a[i]+n)%n;
mp[b[i]]++;
}
for(auto p:mp){
if(p.second+2*m>=n){
// cout<<p.first<<' '<<p.second<<endl;
for(int i=0;i<=n;i++) fa[i]=i;
if(judge(p.first))
ans.push_back(p.first);
}
}
cout<<ans.size();
for(auto i:ans) cout<<' '<<i;
cout<<endl;
}
signed main(){
IOS
#ifndef ONLINE_JUDGE
freopen("IO\\in.txt","r",stdin);
freopen("IO\\out.txt","w",stdout);
#endif
int tn=1;
cin>>tn;
while(tn--){
solve();
}
}