gugu
题意
给定 N ∗ M N*M N∗M的图,只能向下或向右走,有 Q Q Q个限制,必须从 ( a i , b i ) (a_i,b_i) (ai,bi)走到 ( c i , d i ) (c_i,d_i) (ci,di),求从 ( 1 , 1 ) (1,1) (1,1)走到 ( N , M ) (N,M) (N,M)的方案数。
解题
给每个
(
a
i
,
b
i
)
(a_i,b_i)
(ai,bi)赋移动方向,
(
c
i
,
d
i
)
(c_i,d_i)
(ci,di)不在
(
a
i
+
1
,
b
i
)
(a_i+1,b_i)
(ai+1,bi)或
(
a
i
,
b
i
+
1
)
(a_i,b_i+1)
(ai,bi+1)的直接赋
−
1
-1
−1,
(
a
i
,
b
i
)
(a_i,b_i)
(ai,bi)有两个及以上限制的也赋
−
1
-1
−1。然后直接
N
∗
M
N*M
N∗M的基础
D
P
DP
DP推过去就行了:
f
i
,
j
=
f
i
−
1
,
j
∗
(
g
i
−
1
,
j
=
=
1
)
+
f
i
,
j
−
1
∗
(
g
i
,
j
−
1
=
=
2
)
f_{i,j}=f_{i-1,j}*(g_{i-1,j}==1)+f_{i,j-1}*(g_{i,j-1}==2)
fi,j=fi−1,j∗(gi−1,j==1)+fi,j−1∗(gi,j−1==2)
代码
const int mo=1e9+7;
int n,m,t;
int mp[3010][3010];
int f[3010][3010];
int main()
{
freopen("gugu.in","r",stdin);
freopen("gugu.out","w",stdout);
n=gi<int>(),m=gi<int>(),t=gi<int>();
for(int i=1;i<=t;i++)
{
int a,b,c,d;
a=gi<int>(),b=gi<int>(),c=gi<int>(),d=gi<int>();
if(mp[a][b]!=0) mp[a][b]=-1;
else if(a==c && d==b+1) mp[a][b]=1;
else if(b==d && c==a+1) mp[a][b]=2;
else mp[a][b]=-1;
}
f[1][0]=1;
mp[1][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
f[i][j]=(1LL*f[i-1][j]*(mp[i-1][j]==2 || mp[i-1][j]==0)+f[i][j-1]*(mp[i][j-1]==1 || mp[i][j-1]==0))%mo;
pi(f[n][m]);
return 0;
}
letter
题意
一串仅包含 A B C ABC ABC的字符 S S S,一个栈。
三种操作:1.入栈一个字母;2.打印栈顶字母;3.出栈栈顶元素。
求多少次操作可打印出 S S S,打印完需保证栈为空。
解题
枚举中点,中点之前打印字母进行三种操作:
1.栈顶就是要打印的字母,直接打印;
2.栈顶不是,但第二个元素是,出栈然后打印;
3.否则入栈然后打印;
中点之后只考虑出栈不入栈。
就这么简单,但考试的时候只想到了前后的操作,但觉得要不断这样变换操作,后来讨论发现只要枚举一个中点就好了~~,人都傻了~~。
代码
const int N=5010;
int a[N];
int n;
inline void get()
{
char ch[N];
scanf("%s",ch+1);
n=strlen(ch+1);
for(int i=1;i<=n;a[i]=ch[i]-'A'+1,i++);
}
int q[N];
int top=0;
int ans=1e9+10;
int main()
{
freopen("letter.in","r",stdin);
freopen("letter.out","w",stdout);
get();
for(int i=(n>>1);i<=n;i++)
{
int sum=0;
top=0;
for(int j=1;j<=i;j++)
{
if(top>=1 && q[top]==a[j]) sum++;
else if(top>=2 && q[top-1]==a[j]) top--,sum+=2;
else q[++top]=a[j],sum+=2;
}
for(int j=i+1;j<=n;j++)
{
while(top>0 && q[top]!=a[j]) top--,sum++;
if(top==0) break;
sum++;
}
if(top!=0) ans=min(ans,sum+top);
}
pi(ans);
return 0;
}
math
题意
解题
f m i n = ( l − 1 ) ∗ ( l − 1 ) 4 − ( l − 1 ) ∗ ( l − 1 ) 2 + l ∗ l f 最 小 的 数 组 个 数 = C l − 1 2 − 1 n − l − 1 2 − 2 f_{min}=\frac{(l-1)*(l-1)}4-\frac{(l-1)*(l-1)}2+l*l \\ f最小的数组个数=C^{n-\frac{l-1}2-2}_{\frac{l-1}2-1} fmin=4(l−1)∗(l−1)−2(l−1)∗(l−1)+l∗lf最小的数组个数=C2l−1−1n−2l−1−2
代码
const int mo=1e9+7;
ll n,l,ans;
int flg;
ll qmul(ll a,int b){ll sum=1;while(b){if(b&1)
sum=sum*a%mo;a=a*a%mo,b>>=1;}return sum;}
ll C(ll n,ll m)
{
ll s1=1,s2=1;
for(int i=1;i<=m;i++) s1=s1*(n-i+1)%mo;
for(int i=1;i<=m;i++) s2=s2*i%mo;
return s1*qmul(s2,mo-2)%mo;
}
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
gi(n),gi(l),gi(flg);
ans=(l-1)>>1;
pi(ans*ans-(l-1)*ans+l*l);
if(flg)
{
ll mx=n-1-(ans<<1);
pi(C(mx+ans-1,ans-1));
}
return 0;
}