題目沒連接,除了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;
}