9.29模考
T1 打表(table)
Sol
所谓最优不最优都是假的。因为显然当一个取法最优的时候,其对立面就是最不优的,而每次选择优和不优是等概率的,所以实际上每个数都是等概选取,答案就是所有数与原数的差的绝对值之和除\(2^k\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p=1000000007,maxn=1000010;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
return f?x:-x;
}
inline int ksm(int x,int mi)
{
int ans=1;
while(mi)
{
if(mi&1)ans=ans*x%p;
x=x*x%p;mi>>=1;
}
return ans;
}
int n,k,a[maxn];
signed main()
{
freopen("table.in","r",stdin);
freopen("table.out","w",stdout);
k=read();n=read();
int m=1<<k;
for(int i=0;i<m;i++)a[i]=read();
int sum=0;
for(int i=0;i<m;i++)
{
sum+=abs(a[i]-a[n]);
}
sum%=p;
printf("%lld\n",sum*ksm(m,p-2)%p);
return 0;
}
T2 蛇(snake)
Sol
因为只有两行,所以蛇的轨迹一定可以拆分成三部分:向前然后调头、s形扭曲前进、向后然后调头。
向前调头和向后调头的部分可以哈希解决,而中间的s形部分考虑DP。
设\(dp[i][j][k][0]、dp[i][j][k][1]\)分别表示到\(i,j\)的位置蛇到\(k\)位置时,有/没有变道的方案数。
那么显然有
\[dp[i][j][k][0]+=dp[i][j-1][k-1][0]+dp[i][j-1][k-1][1]
\]
\[dp[i][j][k][1]+=dp[i^1][j][k-1][0]
\]
前后的哈希部分要注意方向即可。
由于蛇的方向不固定,所以要反向在跑一遍。但是上下没有方向,所以当蛇长为\(1\)或\(2\)时需要特殊处理,减去重复部分。
不知道为什么挂了的code
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef unsigned long long ull;
const int maxn=2010,p=1000000007;
int dp[2][maxn][maxn<<1][2];//行、列、路径长、是否换行
ull hash1[2][2][maxn],hash2[maxn];
ull bw[maxn];
ull gethash1(int x,bool flag,int st,int t)
{
if(flag)return hash1[x][flag][t]-hash1[x][flag][st+1]*bw[st-t+1];
return hash1[x][flag][t]-hash1[x][flag][st-1]*bw[t-st+1];
}
ull gethash2(int st,int t)
{
return hash2[t]-hash2[st-1]*bw[t-st+1];
}//哈希
int n,l,ans;
char s[maxn];
int a[2][maxn],snk[maxn];
inline void pre()
{
for(int i=0;i<2;i++)
{
for(int j=1;j<=n;j++)
{
hash1[i][0][j]=hash1[i][0][j-1]*107+a[i][j];
}
}
for(int i=0;i<2;i++)
{
for(int j=n;j>=1;j--)
{
hash1[i][1][j]=hash1[i][1][j+1]*107+a[i][j];
}
}
return;
}
inline void work()
{
pre();//预处理哈希
for(int i=0;i<2;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]==snk[1])dp[i][j][1][0]=1;//第一段预处理
for(int k=2;k<=j;k++)
{
if(k<<1>l)break;
if(gethash1(i,0,j-k+1,j)==gethash2(1,k)&&gethash1(i^1,1,j,j-k+1)==gethash2(k+1,k<<1))dp[i][j][k<<1][1]=1;
}
}
}
for(int k=1;k<=l;k++)
{
for(int i=0;i<2;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]!=snk[k])continue;
dp[i][j][k][0]=(dp[i][j][k][0]+dp[i][j-1][k-1][0]+dp[i][j-1][k-1][1])%p;//直走
dp[i][j][k][1]=(dp[i^1][j][k-1][0]+dp[i][j][k][1])%p;//蛇形转向
}
}
}
for(int i=0;i<2;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=0;k<=l;k++)
{
if((l-k)%2!=0)continue;
int le=(l-k)>>1;
if(le==1)continue;
if(j+le>n)continue;
if(k==l||gethash1(i,0,j+1,j+le)==gethash2(k+1,k+le)&&gethash1(i^1,1,j+le,j+1)==gethash2(k+le+1,l))
{
ans=(ans+dp[i][j][k][0]+dp[i][j][k][1])%p;
}
}
}
}
return;
}
signed main()
{
freopen("snake.in","r",stdin);
freopen("snake.out","w",stdout);
scanf("%s",s+1);n=strlen(s+1);
for(int i=1;i<=n;i++)a[0][i]=s[i]-'a';
scanf("%s",s+1);
for(int i=1;i<=n;i++)a[1][i]=s[i]-'a';
scanf("%s",s+1);l=strlen(s+1);
bw[0]=1;
for(int i=1;i<=l;i++)
{
snk[i]=s[i]-'a';
hash2[i]=hash2[i-1]*107+snk[i];
bw[i]=bw[i-1]*107;
}
work();
reverse(a[0]+1,a[0]+n+1);
reverse(a[1]+1,a[1]+n+1);
memset(dp,0,sizeof(dp));
work();
if(l==1)
{
for(int i=0;i<2;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]==snk[1])ans--;
}
}
}
if(l==2)
{
for(int i=0;i<2;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]==snk[1]&&a[i^1][j]==snk[2])ans--;
}
}
}
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号