A题:
链接:https://nanti.jisuanke.com/t/41383
思路:模型是经典常见的斐波拉契博弈模型,套上一个java大数的扩展中国剩余定理即可。
扩展中国剩余定理解出方程,判断一下解出的数是否是斐波拉契数即可。
代码是java的就不贴了。
B题:
链接:https://nanti.jisuanke.com/t/41384
思路:
map加路径压缩,其实就是类似于并查集找fa一样,不过是用map存储fa数组的,(因为点的个数1e9个,数组开不下),使用unordered_map并且判断没有被map映射过时用的是!mp.count(x),直接判断mp[x]的值是不是0来判断是否被map标记过时不管这一点的map值是不是0都会再把这个点加入到map一次,可能会t。
(ps:听说直接map标记然后暴力向后面找没有t,这数据简直弱的。。orzz)
AC代码:
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> mp;
const int maxn=1e6+50;
int n,m;
int find(int x)
{
if(!mp.count(x)) return x;
else
{
return mp[x]=find(mp[x]);
}
return mp[x];
}
int main()
{
scanf("%d%d",&n,&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
if(a==1) mp[b]=find(b+1);
else printf("%d\n",find(b));
}
return 0;
}
C题:
链接:https://nanti.jisuanke.com/t/41385
思路:本场最简单的签到题,思路是把一个西瓜切成两部分,(注意,切出来的两部分不一定要完全相等的两部分),如果存在一种切法使得切出来的两部分的质量都是偶数,就输出YES,否则就输出NO。
判断一下是不是偶数,奇数肯定不行,偶数的话2要特判不行,别的偶数都输出YES。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
if(n==2)
{
cout<<"NO"<<endl;
return 0;
}
else
{
if(n%2==1) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
D题:
链接:https://nanti.jisuanke.com/t/41386
思路:题目意思就是一个模式串和很多个文本串,大概就是对于每一个文本串比较一下模式串和文本串的长度大小,然后对于>,<,=三种情况分别判断一下子串关系对应输出2*3种不同的字符串就行了。
一开始想的是对于比模式串长度小和等于的那些串统一用AC自动机处理,对于长度大于模式串的使用kmp来判断子串关系,这样可能不会超时,后来一看所有的字符串的总长度的和不超过1e7,给的1s好像kmp就直接能跑过去并且过的人那么多,就直接写了kmp莽过去了。
AC代码:kmp裸题了
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+500;
char s1[maxn];
char s2[maxn];
int q;
int nxt[maxn];
void get_next(char *str)
{
int i=0;int j=-1;nxt[0]=-1;
int len=strlen(str);
while(i<len)
{
if(j==-1||str[i]==str[j]) nxt[++i]=++j;
else j=nxt[j];
}
}
int kmp(char *s1,char *s2)
{
get_next(s2);
int len=strlen(s2);
int i,j;i=j=0;
int len1=strlen(s1);int len2=strlen(s2);
while(i<len1)
{
if(j==-1||s1[i]==s2[j]) i++,j++;
else j=nxt[j];
if(j>=len2)
{
return 1;
}
}
return 0;
}
int main()
{
scanf("%s",s1);
scanf("%d",&q);
while(q--)
{
scanf("%s",s2);
int n1=strlen(s1);
int n2=strlen(s2);
if(n1==n2)
{
int fin=kmp(s1,s2);
if(fin) printf("jntm!\n");
else printf("friend!\n");
}
if(n1>n2)
{
int fin=kmp(s1,s2);
if(fin) printf("my child!\n");
else printf("oh, child!\n");
}
if(n1<n2)
{
int fin=kmp(s2,s1);
if(fin) printf("my teacher!\n");
else printf("senior!\n");
}
}
return 0;
}
E题:
链接:https://nanti.jisuanke.com/t/41387
思路:学长说是权值线段树裸题,直接敲过去了,题解好像说了一个更简单好实现的方法,稍后如果补了就发上来。
G题:
链接:https://nanti.jisuanke.com/t/41389
思路:学长回文自动机写的,好像是回文自动机和dfs啥的,我是真实躺狗石锤了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
char s[300010];
int Len;
ll ans;
struct PAM{
ll next[maxn][26],fail[maxn],len[maxn];;
ll txt[maxn];
ll root0,root1,last,size;
ll tot;
ll mx;
ll num[maxn];
ll sum;
ll cnt[maxn];
void init(){
last=tot=size=0; txt[size]=-1;mx=0;sum=0;
memset(cnt,0,sizeof(cnt));
memset(num,0,sizeof(num));
root0=newnode(0); root1=newnode(-1);
fail[root0]=1; fail[root1]=0;
}
int newnode(int l){
len[tot]=l;
mx=max(mx,l*1ll);
memset(next[tot],0,sizeof(next[tot]));
tot++; return tot-1;
}
int getfail(int x){
while(txt[size-len[x]-1]!=txt[size]) x=fail[x];
return x;
}
void extend(int c){
txt[++size]=c; int now=getfail(last);
if(!next[now][c]){
int tmp=newnode(len[now]+2);
fail[tmp]=next[getfail(fail[now])][c];
next[now][c]=tmp;
num[tmp]=num[fail[tmp]]+1;
}
last=next[now][c];
cnt[last]++;
sum+=num[last];
}
void cal(){
for(int i=tot;i>=2;i--){
cnt[fail[i]]+=cnt[i];
}
}
void dfs(int u,int color,int res){
ans+=1ll*res*cnt[u];
for(int i=0;i<26;i++){
if(next[u][i]){
if(color&(1<<i)){//颜色出现过
dfs(next[u][i],color,res);
}else{
dfs(next[u][i],color|(1<<i),res+1);
}
}
}
}
}pam;
int main(){
//ios::sync_with_stdio(false);
scanf("%s",&s);
ans=0;
pam.init();
Len=strlen(s);
for(int i=0;i<Len;i++) pam.extend(s[i]-'a');
pam.cal();
pam.dfs(0,0,0);
pam.dfs(1,0,0);
printf("%lld\n",ans);
return 0;
}
K题
链接:https://nanti.jisuanke.com/t/41393
思路:
M题:
链接:https://nanti.jisuanke.com/t/41395
思路:吃个饭回来补,好饿。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+50;
char s1[maxn];
char s2[maxn];
vector<int> pos[30];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s1+1);
scanf("%s",s2+1);
for(int i=1;i<=n;i++)
{
int z=s1[i]-'a';
pos[z].push_back(i);
}
vector<int>::iterator it1;
vector<int>::iterator it2;
int mx=-1;
int flag1=1;
int now=-1;
int cnt=0;
for(int i=1;i<=m;i++)
{
if(!flag1) break;
int z=s2[i]-'a';
for(int j=z+1;j<='z'-'a';j++)
{
it1=upper_bound(pos[j].begin(),pos[j].end(),now);
if(it1==pos[j].end()) continue;
else//找到了大的方案
{
int jj=*it1;
mx=max(mx,n-jj+1+cnt);
}
}
it2=upper_bound(pos[z].begin(),pos[z].end(),now);
if(it2==pos[z].end()) flag1=0;
else
{
int jj=*it2;
now=jj;
cnt++;
if(cnt==m)
{
if(n-now==0) continue;
else mx=max(mx,cnt+n-now);
}
}
}
printf("%d\n",mx);
return 0;
}