JZOJ 3843 尋找羔羊
題目
給定一個由小寫字母組成的字符串,尋找包含agnus的子串的個數。注意:當且僅當兩個子串的起始位置和終點不同時,這兩個子串屬於不同的子串。
分析
若找到一個羔羊單詞,那麼計算左右可擴展的範圍,乘起來再求和即可
代碼
#include <cstdio>
#include <cstring>
#define rr register
using namespace std;
char s[30011]; int n,ans;
signed main(){
scanf("%s",s+1);
n=strlen(s+1); rr int st=0;
for (rr int i=5;i<=n;++i)
if (s[i-4]=='a'&&s[i-3]=='g'&&s[i-2]=='n'&&s[i-1]=='u'&&s[i]=='s'){
ans+=(n-i+1)*(i-4-st);
st=i-4;
}
return !printf("%d",ans);
}
JZOJ 3844 統計損失
題目
求一棵樹上任意兩點(可以相同)間的邊權之積的和
分析
設表示以爲根的子樹所形成一端爲的簡單路徑的邊權之積的和,那麼
設表示以爲根的子樹所形成的兩端都不爲的簡單路徑的邊權之積的和,那麼
把兩者加起來就是答案
代碼
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int mod=10086,N=100011;
struct node{int y,next;}e[N<<1];
int dp[N],f[N],ls[N],a[N],n,k=1;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline void dfs(int x,int fa){
rr int sum=0;
for (rr int i=ls[x];i;i=e[i].next)
if (e[i].y!=fa){
dfs(e[i].y,x); rr int now=a[x]*dp[e[i].y]%mod;
f[x]=mo(f[x],sum*now%mod);
dp[x]=mo(dp[x],now);
sum=mo(sum,dp[e[i].y]);
}
dp[x]=mo(dp[x],a[x]);
}
signed main(){
n=iut();
for (rr int i=1;i<=n;++i) a[i]=iut()%mod;
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut();
e[++k]=(node){y,ls[x]},ls[x]=k,
e[++k]=(node){x,ls[y]},ls[y]=k;
}
dfs(1,0); rr int ans=0;
for (rr int i=1;i<=n;++i) ans=mo(ans,mo(dp[i],f[i]));
return !printf("%d",ans);
}
JZOJ 3845 簡單題
題目
在一個無向圖中找到存在一條簡單路徑使順次連接的仙人掌,問這個仙人掌的最大邊數
分析
首先有條邊是必須的,設表示所組成的仙人掌所能含的最大邊數,那麼,表示某個右端點所擁有的邊中最大的左端點
代碼
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=100011;
int n,m,ans,dp[N],pre[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void Mx(int &a,int b){a=a>b?a:b;}
signed main(){
n=iut(); m=iut();
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut();
if (x>y) x^=y,y^=x,x^=y;
if (x+1<y&&pre[y]<x) pre[y]=x;
}
for (rr int i=1;i<=n;++i){
dp[i]=dp[i-1];
if (pre[i]) Mx(dp[i],dp[pre[i]]+1);
}
return !printf("%d",dp[n]+n-1);
}