题目没连接,除了Upc,没找到其他开发OJ有此题,如果有连接,请评论区留言下,谢谢~
A题:
题意:给你一个字符串问你只有一种字母的子串有多少。
思想:直接暴力连续的字符串数 结果等于每个连续字符的(长度*长度+1)/2
B 题:
不会~
C题
题意:给你x1,x2,y1,y2,(x1<x2,y1<y2)问你从x1到y1的同时x2到y2不想交的路径有多少
思想:Lindström–Gessel–Viennot定理 解决DAG图中n条不交叉路径问题,比赛的时候知道是这个但是脑子瓦特了,烦。
定理可以看下这个博客:https://blog.csdn.net/ftx456789/article/details/81132126
逆元预处理组合数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod =1e9+7;
const int maxn=1e6+5;
ll fac[maxn],inv[maxn];
inline ll qpow(ll a,ll b){ll r=1,t=a; while(b){if(b&1)r=(r*t)%mod;b>>=1;t=(t*t)%mod;}return r;}
void init()
{
fac[0]=1;
for (int i=1;i<maxn;i++)
fac[i]=fac[i-1]*i%mod;
inv[maxn-1]=qpow(fac[maxn-1],mod-2);
for (int i=maxn-2;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(ll n,ll m){
if (n<m) return 0;
return ((fac[n]*inv[m]%mod)%mod*inv[n-m]%mod)%mod;
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
ll a,b,c,d;
scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
ll temp=(C(a+c,a)*C(b+d,b))%mod;
ll Temp=(C(a+d,a)*C(b+c,b))%mod;
temp=(temp-Temp+mod)%mod;
printf("%lld\n",temp);
}
return 0;
}
D题
题意:给你n个数,然后m次询问,每次问你区间的数,是否是连续的数。
思想:莫队维护区间,RMQ求区间最值。莫队维护区间不同数的个数,RMQ求一下区间最大和最小值,看下当前区间出现的数是否等于Max-Min+1个即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int b[maxn];
int kuai[maxn];
int vis[maxn];
int Maxx[maxn][25];
int Minn[maxn][25];
int cnt[maxn];
struct node{
int l;
int r;
int id;
}no[maxn];
int ans,n,m;
int cmp(node a,node b)
{
if(kuai[a.l]==kuai[b.l])
return a.r<b.r;
return a.l<b.l;
}
void init()
{
for(int j=1;j<=20;j++)
{
for(int i=1;i+(1<<j)<=n+1;i++)
{
Maxx[i][j]=max(Maxx[i][j-1],Maxx[i+(1<<(j-1))][j-1]);
Minn[i][j]=min(Minn[i][j-1],Minn[i+(1<<(j-1))][j-1]);
}
}
}
int RMQmax(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1)
k++;
return max(Maxx[l][k],Maxx[r-(1<<k)+1][k]);
}
int RMQmin(int l,int r)
{
int k=0;
while((1<<(k+1))<=r-l+1)
k++;
return min(Minn[l][k],Minn[r-(1<<k)+1][k]);
}
void add(int l)
{
cnt[a[l]]++;
if(cnt[a[l]]==1)
ans++;
}
void del(int l)
{
cnt[a[l]]--;
if(cnt[a[l]]==0)
ans--;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(cnt,0,sizeof(cnt));
scanf("%d%d",&n,&m);
int black=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
kuai[i]=i/black+1;
Maxx[i][0]=a[i];
Minn[i][0]=a[i];
}
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&no[i].l,&no[i].r);
no[i].id=i;
}
sort(b+1,b+1+n);
int k=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++)
a[i]=lower_bound(b+1,b+1+k,a[i])-b;
int l=1;
int r=0;
ans=0;
sort(no+1,no+1+m,cmp);
for(int i=1;i<=m;i++)
{
while(l<no[i].l)
del(l++);
while(l>no[i].l)
add(--l);
while(r<no[i].r)
add(++r);
while(r>no[i].r)
del(r--);
int Max=RMQmax(no[i].l,no[i].r);
int Min=RMQmin(no[i].l,no[i].r);
if(Max-Min==ans-1)
vis[no[i].id]=1;
else
vis[no[i].id]=0;
}
for(int i=1;i<=m;i++)
{
if(vis[i]==1)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
E题
题意:给你x,y。问你x个东西均分y个人,让其中获得最多的人和最小的人的差值最小。
思路:x%y==0 则是0否则是1
F题
题意:给你2个串,问你A的子串和B的子串(长度相等)不同位置不超过k,这个子串的长度最长为多少。
思想:枚举A的子串的起点去匹配B串,枚举B串子串的起点去匹配A串。匹配的时候尺取法去匹配。n^2*T=8e7
#include<bits/stdc++.h>
using namespace std;
int k,ans;
char a[4005];
char b[4005];
void check(char c[],char d[])
{
int sum=0;//标记已经有多少个不同
int len=min(strlen(c),strlen(d));
for(int l=0,r=-1;l<len;l++)
{
while(r+1<len && sum+(c[r+1]!=d[r+1])<=k)
{
r++;
sum+=c[r]!=d[r];
}
ans=max(ans,r-l+1);
sum-=(c[l]!=d[l]);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&k);
scanf("%s%s",a,b);
ans=0;
int Len=strlen(a);
for(int i=0;i<Len;i++)
check(a+i,b);
Len=strlen(b);
for(int i=0;i<Len;i++)
check(b+i,a);
printf("%d\n",ans);
}
return 0;
}
G题
题意:给你n个花的高度,每次修改n-1盆花,问你是否出现所有花一样高的局面,没有输出-1,有的话输出最少的时间。
思想:假设a[0]减去X下,a[1]减去Y下,a[2]减去Z下~~~~~这样先将全部拍个序列,考虑如果所有的花减去的长度等于sigma(max-a[i])(i>=1 && i<=n)的话,这样所有的花都到了一个统一的高度,考虑最矮的那个花是否可以sum-(Max-a[0])>0,如果不行的话那么就输出-1,如果行的话,那么输出就等于sum。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
int ans=0;
for(int i=1;i<n;i++)
ans+=a[n-1]-a[i];
if(ans>=a[0])
printf("-1\n");
else
printf("%d\n",ans+a[n-1]-a[0]);
}
return 0;
}
H题
题意:就是给你n个立方体的边长和密度,然后给你一个底面积为S,高为H,现在有V体积水的一个容器,然后问你最后水的高度。
思想:我深切感觉题意有问题,题意没有说明重的一定都会没进去,可能出题人的没表达清楚?或者我菜?
密度>=1 全放进去,小于1的就按照比例放就好了,别忘了加上原来的水就行了。
I题
据说是AC自动机+DP
J题
题意:给你一个序列,问你最少交换多少次可以让序列变回一个有序的序列。
思想:如果是交换相邻的话,就变成了求逆序对,然而是随意交换的话,就相等于判断有多少个环即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int b[maxn];
int vis[maxn];
int Vis[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
memset(vis,0,sizeof(vis));
memset(Vis,0,sizeof(Vis));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b,b+n);
for(int i=0;i<n;i++)
Vis[b[i]]=i;
int ans=n;
for(int i=0;i<n;i++)
{
if(vis[i]==0)
{
int temp=i;
while(vis[temp]==0) //跑一个环
{
vis[temp]=1;
temp=Vis[a[temp]];
}
ans--;//一个环少交换一次
}
}
printf("%d\n",ans);
}
return 0;
}