JZOJ 1764 游戏
分析
可以求出第一行的系数,再深搜解决,只能说深搜按照某种意义上是过不了的,但是由于这道题正解就是这样,所以也无可奈何
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
struct rec{int x,y;}a[101];
int n,m,maxx,ans,now=1,flag,f[2][101],b[101];
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;
}
bool cmp(rec a,rec b){return a.x>b.x||(a.x==b.x&&a.y<b.y);}
void dfs(int dep,int sum){
if (ans<sum) return;
if (dep>n){
if (ans==sum) flag=1;
return;
}
if (!f[now][dep]) {dfs(dep+1,sum); return;}
rr int t=(ans-sum)/f[now][dep];
t=t>maxx?maxx:t;
for (rr int i=0;i<=t;++i){
b[dep]=i; dfs(dep+1,sum+f[now][dep]*i);
if (flag) return;
}
}
signed main(){
n=iut(); m=iut(); maxx=iut(); ans=iut();
for (rr int i=1;i<=m;++i) a[i]=(rec){iut(),iut()};
sort(a+1,a+1+m,cmp); f[now][1]=1;
for (rr int i=2,k=1;i<=n;++i){
for (rr int j=1;j<=i;++j) f[now^1][j]=f[now][j-1]+f[now][j];
for (rr int j=1;j<=i;++j)
if (n-i+1==a[k].x&&j==a[k].y)
++k,f[now^1][j]=0;
now^=1;
}
dfs(1,0);
if (!flag) printf("-1");
else for (rr int i=1;i<=n;++i) printf("%d\n",b[i]);
return 0;
}
JZOJ 1764 过河
分析
真的只是一个暴力+玄学???
暴力答案,用布尔数组判断该时刻是否可到达
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
bool dp[2][1011]; int upp[1011],dow[1011];
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 min(int &a,int b){if (a>b) a=b;}
signed main(){
for (rr int t=iut();t;--t){
rr int n=iut(),ans=1,flag=0;
for (rr int i=1;i<=n;++i) upp[i]=iut(),dow[i]=iut();
memset(dp,0,sizeof(dp));
for (;ans<601;++ans){
memset(dp[ans&1],0,sizeof(dp[ans&1]));
dp[(ans&1)^1][0]=1;
for (rr int i=1;i<=n;++i)
if ((ans-1)%(upp[i]+dow[i])+1>upp[i]) dp[ans&1][i]=0;
else for (rr int j=i<5?0:i-5;j<i+6;++j) dp[ans&1][i]|=dp[(ans&1)^1][j];
flag=dp[ans&1][n]|dp[ans&1][n-2]|dp[ans&1][n-1]|dp[ans&1][n-3]|dp[ans&1][n-4];
if (flag) break;
}
if (flag) printf("%d\n",ans+1); else printf("No\n");
}
return 0;
}
JZOJ 4669 弄提纲
题目
问以 l l l和 r r r结尾的字符串的公共后缀中,有多少个是原串的前缀,以及公共后缀与原串前缀的最大公共长度
分析
可以思考 K M P KMP KMP中的失配数组也就是所谓的最大公共长度,那么可以考虑一个点的失配连接该点,从字符串开头跑一遍广搜,那么深度也就是有多少种公共前后缀的可能,最大公共长度也就是 l c a ( l , r ) lca(l,r) lca(l,r),考虑用求 l c a lca lca的 t a r j a n tarjan tarjan解决
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=30011;
struct node{int y,next;}e[N],ee[200011]; char s[N];
int f[N],v[N],dep[N],ls[N],lls[N],ans[200011],fail[N],m,k=1,kk=1,len;
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;
}
signed getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
inline void dfs(int x){
f[x]=x; v[x]=1;
for (rr int i=ls[x];~i;i=e[i].next)
if (!v[e[i].y]){
dep[e[i].y]=dep[x]+1;
dfs(e[i].y); f[e[i].y]=x;
}
for (rr int i=lls[x];~i;i=ee[i].next)
if (v[ee[i].y]) ans[i]=ans[i^1]=getf(ee[i].y);
}
signed main(){
memset(ls,-1,sizeof(ls));
memset(lls,-1,sizeof(lls));
rr char c=getchar();
while (isalpha(c)) s[++len]=c,c=getchar();
m=iut();
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut();
ee[++kk]=(node){y,lls[x]}; lls[x]=kk;
ee[++kk]=(node){x,lls[y]}; lls[y]=kk;
}
for (rr int i=2,j=0;i<=len;++i){
while (j&&s[i]!=s[j+1]) j=fail[j];
fail[i]=(j+=(s[i]==s[j+1]));
}
for (rr int i=1;i<=len;++i)
e[++k]=(node){i,ls[fail[i]]},ls[fail[i]]=k;
dfs(0);
for (rr int i=1;i<=m;++i)
printf("%d %d\n",dep[ans[i<<1]],ans[i<<1]);
return 0;
}