2023.5.29测试
T2~T4 全是计数题,败了
T2 网格
只会这一题
两种方案不同是指:存在某行或者某列,在两种方案中,操作的次数不同。
从对不同方案的定义,加上一点手推及猜想可知,两种操作的顺序并不会对最终的结果造成影响。也就是说,当我们知道哪行哪列进行过奇数次操作,我们就可以推出最后有多少个
我们枚举实际有用的操作次数
预处理组合数,
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1600,MOD=555555555;
int T,n,m,r,c,s;
LL f[2*N][2*N],ans;
void prework()
{
for(int i=0; i<=2*1555; i++)
f[i][0]=1;
for(int i=1; i<=2*1555; i++)
for(int j=1; j<=i; j++)
f[i][j]=(f[i-1][j]+f[i-1][j-1])%MOD;
}
int main()
{
prework();
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d%d",&n,&m,&r,&c,&s);
ans=0;
for(int i=0; i<=min(r,n); i++)
{
if((r-i)%2!=0)
continue;
for(int j=0; j<=min(c,m); j++)
{
if((c-j)%2!=0)
continue;
if(n*j+m*i-2*i*j!=s)
continue;
int k=(r-i)/2,t=(c-j)/2;
LL tmp=1LL*f[n][i]*f[k+n-1][n-1]%MOD*f[m][j]%MOD*f[t+m-1][m-1]%MOD;
(ans+=tmp)%=MOD;
}
}
printf("%lld\n",ans);
}
return 0;
}
T3 双数组
求有多少对不同的数组
均有 个数
脑瘫了没想出来
考场上用
其实是道简单的容斥题
不考虑第
枚举
#include<bits/stdc++.h>
using namespace std;
const int N=500010,MOD=1000000007;
int n,s,ans;
int fac[N],inv[N];
int ksm(int x,int y)
{
int res=1;
while(y)
{
if(y&1)
res=(1LL*res*x)%MOD;
x=(1LL*x*x)%MOD;
y>>=1;
}
return res;
}
void prework()
{
fac[0]=1; inv[0]=1;
for(int i=1; i<=s; i++)
{
fac[i]=(1LL*fac[i-1]*i)%MOD;
inv[i]=ksm(fac[i],MOD-2);
}
}
int A(int a,int b)
{
return 1LL*fac[a]*inv[a-b]%MOD;
}
int C(int a,int b)
{
if(b==0)
return 1;
return 1LL*fac[a]*inv[a-b]%MOD*inv[b]%MOD;
}
int main()
{
scanf("%d%d",&n,&s);
prework();
ans=1LL*A(s,n)*A(s,n)%MOD;
for(int i=1; i<=n; i++)
{
int a=C(n,i),b=A(s,i),c=A(s-i,n-i);
if(i&1)
ans=(ans-1LL*a*b%MOD*c%MOD*c%MOD+MOD)%MOD;
else
ans=(ans+1LL*a*b%MOD*c%MOD*c%MOD)%MOD;
}
printf("%d",ans);
return 0;
}
T4 字符串
给定一个原串
只看了题根本没写
法一:
从结果开始考虑,设
显然
有一种“套路”,我们考虑
因此,我们枚举最后一个字符出现的位置
len=strlen(s);
n+=len;
prework(); //预处理阶乘、逆元,和上题一样
for(int i=len; i<=n; i++)
(ans+=1LL*ksm(25,i-len)*ksm(26,n-i)%MOD*C(i-1,len-1)%MOD)%=MOD;
printf("%d",ans);
法二:
大佬hpz倾情提供
其实考场上不一定想得出套路,但一定有能力爆搜。hpz通过爆搜发现答案和
for(int i=len; i<=n; i++)
(ans+=1LL*C(n,i)*ksm(25,n-i)%MOD)%=MOD;
其实还有mzm大佬的
T5 赠送笔记本
有
又是插入
本题的赠送方案涉及往前也有往后,所以用插入
首先我们考虑接收前面的。设
再考虑往前送。设
综上,得出状态转移方程:
时间复杂度
prework();
int sum=0;
f[0][0]=1;
for(int i=1; i<=n; i++)
{
for(int j=0; j<=sum; j++)
{
for(int k=0; k<=4; k++)
{
for(int t=0; t<=a[i]; t++)
{
int s=4*(i-1)-(sum-j);
LL x=A(j,k)*C(4,k)%MOD,y=C(a[i],t)*A(s,t);
(f[i][j-k+(a[i]-t)]+=f[i-1][j]*x%MOD*y%MOD)%=MOD;
}
}
}
sum+=a[i];
}
printf("%lld",f[n][0]);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】