noip模拟45
A. 打表
不知道该怎么想到这一类的题.
看起来像是推理性质,然后得到一个复杂度简洁的式子吧..
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigend ll
#define re register ll
#define lf double
#define lbt(x) (x&(-x))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
inline ll read() {
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll mod=1e9+7;
const ll N=1<<19;
ll n,m,ans;
ll w[N];
inline ll ksm(ll a,ll b,ll c){
a%=c; ll temp=1;
while(b){
if(b&1) temp=(temp*a)%c;
a=(a*a)%c,b>>=1;
}
return temp%c;
}
signed main(){
n=read(),m=read();
for(re i=0;i<(1<<n);++i) w[i]=read();
for(re i=0;i<(1<<n);++i)
(ans+=abs(w[i]-w[m]))%=mod;
ans=(ans*ksm(1ll<<n,mod-2,mod))%mod;
printf("%lld",ans);
return 0;
}
B. 蛇
虽然是字符构成的题目,但如果仅仅局限于\(Hash\)、\(Kmp\)、自动机等算法就太狭隘了.
正解是\(dp\),我们发现向四周转移比较困难,考虑如何简化问题.
经过一种不知名的观察我们可以发现,\(ta\) 的行走路线一定是以下形式.(图来源于网络,非原创)

于是我们第一个蓝线左边可以预处理,两个蓝线之间可以只单方向的\(dp\),第二个蓝线右边可以在\(dp\)之后处理.
发现\(ta\)可以翻转过来再做一遍\(dp\),否则会算少.
特别判断一下 \(len_s==1\) 和 \(len_s==2\) 的情况即可.
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
#define ll long long int
#define ull unsigned ll
#define re register ll
#define lf double
#define lb lower_bound
#define ub upper_bound
#define mp make_pair
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
inline ll read()
{
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll mod=1e9+7,N=2e3+11;
const ull P=131;
char s[N];
ll n,m,ans;
ull w[N],pw[N],po[N];
ull c[3][N],pc[3][N],sc[3][N];
ll dp[3][N][N][2];
inline void Pre(){
scanf("%s",s+1); n=strlen(s+1); for(re i=1;i<=n;++i) c[1][i]=s[i]-'a'+1;
scanf("%s",s+1); for(re i=1;i<=n;++i) c[2][i]=s[i]-'a'+1;
scanf("%s",s+1); m=strlen(s+1); for(re i=1;i<=m;++i) w[i]=s[i]-'a'+1;
for(re i=1;i<=2;i++){
for(re j=1;j<=n;j++) pc[i][j]=pc[i][j-1]*P+c[i][j];
for(re j=n;j>=1;j--) sc[i][j]=sc[i][j+1]*P+c[i][j];
}
ll tmp=max(n,m); po[0]=1;
for(re i=1;i<=tmp;i++) po[i]=po[i-1]*P;
for(re i=1;i<=m;i++) pw[i]=pw[i-1]*P+w[i];
}
inline ull getw(ll l,ll r){ return pw[r]-pw[l-1]*po[r-l+1]; }
inline ull getpc(ll i,ll l,ll r){ return pc[i][r]-pc[i][l-1]*po[r-l+1]; }
inline ull getsc(ll i,ll l,ll r){ return sc[i][l]-sc[i][r+1]*po[r-l+1]; }
inline void Match(){
for(re i=1;i<=2;i++){
for(re j=1;j<=n;j++) pc[i][j]=pc[i][j-1]*P+c[i][j];
for(re j=n;j>=1;j--) sc[i][j]=sc[i][j+1]*P+c[i][j];
}
for(re i=1;i<=2;i++){
for(re j=1;j<=n;j++){
dp[i][j][1][0]=(w[1]==c[i][j]); // 上下没有被占为 0
for(re k=2;k<=j;k++){
dp[i][j][k<<1][1]=(getsc(3-i,j-k+1,j)==getw(1,k) and getpc(i,j-k+1,j)==getw(k+1,k<<1));
}
}
}
for(re k=1;k<=m;k++){
for(re i=1;i<=2;i++)
for(re j=1;j<=n;j++){
if(w[k]!=c[i][j]) continue;
(dp[i][j][k][0]+=(dp[i][j-1][k-1][1]+dp[i][j-1][k-1][0])%mod)%=mod,
(dp[i][j][k][1]+=dp[3-i][j][k-1][0])%=mod;
}
}
ll len;
for(re i=1;i<=2;i++){
for(re j=1;j<=n;j++)
for(re k=0;k<=m;k++){
len=(m-k)>>1;
if(len==1 or (m&1)!=(k&1)) continue ;
if(k==m) { ans=(ans+dp[i][j][k][1]+dp[i][j][k][0])%mod; continue; }
if(getpc(i,j+1,j+len)==getw(k+1,k+len) and getsc(3-i,j+1,j+len)==getw(m-len+1,m) and j+len<=n)
ans=(ans+dp[i][j][k][1]+dp[i][j][k][0])%mod;
}
}
}
signed main(){
Pre(); Match();
if(m==1) printf("%lld\n",ans%mod),exit(0);
reverse(c[1]+1,c[1]+1+n),reverse(c[2]+1,c[2]+1+n);
Fill(dp,0);
Match();
if(m==2){
for(re i=1;i<=2;i++){
for(re j=1;j<=n;j++)
ans=(ans-(c[i][j]==w[1] and c[3-i][j]==w[2])+mod)%mod;
}
}
printf("%lld\n",ans%mod);
exit(0);
}
C. 购物
签到题.
这里用了二分,随便判判就行了..
C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigend ll
#define re register ll
#define lf double
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
inline ll read() {
ll ss=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
return cit?ss:-ss;
}
} using namespace BSS;
const ll N=2e5+51;
ll m,n,alls,ans;
ll w[N];
inline ll Get(ll x){
ll l=1,r=n,res=r,mid;
while(l<=r){
mid=(l+r)>>1;
if(w[mid]>=x) r=mid-1,res=mid;
else l=mid+1;
}
return res;
}
signed main(){
n=read();
for(re i=1;i<=n;++i) alls+=w[i]=read();
sort(w+1,w+1+n); ll temp=n,pre=0,now,mid,flag;
for(re i=1;i<=temp;++i)
pre=pre+w[i],w[++n]=pre;
sort(w+1,w+1+n); n=unique(w+1,w+1+n)-w-1;
now=w[n],flag=0;
while(now){
mid=(now+1)>>1,ans+=now-mid+1-flag,temp=Get(mid);
if(now==w[temp]){
now=w[temp-1],flag=0;
}
else{
now=w[temp],flag=now-mid+1;
}
}
printf("%lld",ans);
return 0;
}
D. ants
回滚莫队,先鸽了.

浙公网安备 33010602011771号