今天的题比之前的简单,但我也只拿了5分,主要是T1乘法求逆不会,数据都没法输。
T2我今天才知道queue可以定义一个数组,这样我就可以省去许多
l
l
l,
r
r
r的指针移动的分析qwq~~。
好了,说正事
T1
一道纯数学的题。
已知
p
0
=
0
p_0=0
p0=0,
p
2
n
=
1
p_{2n}=1
p2n=1,
p
i
=
a
∗
p
i
−
1
+
b
∗
p
i
+
c
∗
p
i
+
1
p_i=a*p_{i-1}+b*p_i+c*p_{i+1}
pi=a∗pi−1+b∗pi+c∗pi+1。
根据上式,我们可以推出
p
2
=
(
1
−
b
)
∗
p
i
+
a
∗
p
i
−
1
c
p_2=\frac{(1-b)*p_i+a*p_{i-1}}{c}
p2=c(1−b)∗pi+a∗pi−1,
因此
p
2
=
(
1
−
b
)
∗
p
1
+
a
∗
p
0
c
=
1
−
b
c
∗
p
1
p_2=\frac{(1-b)*p_1+a*p_0}{c}=\frac{1-b}{c}*p_1
p2=c(1−b)∗p1+a∗p0=c1−b∗p1,
p
3
p_3
p3也等于某个常数乘上
p
1
p_1
p1,
不难发现
p
2
n
p_{2n}
p2n也可以用
p
1
p_1
p1表示,然后倒推出
p
n
p_n
pn,得出答案。
还有一种严谨的数学证明做法见sslz_fsy的博客:https://blog.csdn.net/sslz_fsy/article/details/102979580
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M=1e9+7;
const int N=1e7+5;
int read()
{
int x=0,f=1;char ch=0;
while(!isdigit(ch)) {ch=getchar();if(ch=='-') f=-1;}
while(isdigit(ch)) x=(x+(x<<2)<<1)+(ch^48),ch=getchar();
return x*f;
}
int add(int a,int b){return a+b>=M?a+b-M:a+b;}
int mul(int a,int b){ll r=1ll*a*b;if(r>=M) r%=M;return r;}
int ksm(int a,int b){int ans=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) ans=mul(ans,a);return ans;}//快速幂
int n,a,b,x,y,z,f[N<<2];
int main()
{
freopen("experiment.in","r",stdin);
freopen("experiment.out","w",stdout);
n=read();a=read();b=read();
x=mul(add(1,M-a),b);
y=add(mul(add(a,M-1),add(b,M-1)),mul(a,b));
z=mul(a,add(1,M-b));
int vis=ksm(z,M-2);
f[1]=1;
for(int i=2,up=n<<1;i<=up;i++)
{
f[i]=mul(vis,add(mul(add(1,M-y),f[i-1]),M-mul(x,f[i-2])));
}
cout<<mul(ksm(f[n<<1],M-2),f[n]);
return 0;
}
T2
先上题:
这道题就是一个大模拟,题意简单明了。
用一个队列数组维护每个玩家的手牌。
用一个数组维护出牌队列,再用一个bool数组记录一个数是否在出牌队列之中。
用数组ans记录出局的玩家出局的局数,并且玩家的人数减一。
当人数减到一时停止循环。
注意多组数据要清零。
还要注意输出时的空格与换行。
上代码:
#include<bits/stdc++.h>
using namespace std;
#define in read()
int in
{
int i=0;char ch=0;
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
return i;
}
int n,m,t,s,T,siz,top,a[102][105],ans[105],b[100005],sta[100005],tp[100005];
bool insta[10005];
queue<int>q[105];
void init()
{
while(top) insta[sta[top]] = 0,top--;siz = 0;//高级的清零方式(memset太慢)
}
int main()
{
freopen("fishing.in","r",stdin);
freopen("fishing.out","w",stdout);
while(scanf("%d%d%d%d%d",&n,&m,&t,&s,&T),n!=-1)
{
init();
for(int i=1;i<=n;i++)
for(int j=1;j<=t;j++)
a[i][j]=b[++siz]=in;
b[++siz]=s;//离散化
sort(b+1,b+siz+1);
siz=unique(b+1,b+siz+1)-(b+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=t;j++)
{
a[i][j]=lower_bound(b+1,b+siz+1,a[i][j])-b;
q[i].push(a[i][j]);
}
s=lower_bound(b+1,b+siz+1,s)-b;
int N=n;
for(int i=1;i<=T;i++)
{
if(N<=1) break;
for(int j=1;j<=n;j++)
{
if(ans[j]) continue;
int x=q[j].front();
q[j].pop();
if(insta[x])//特判x在sta中的情况
{
int res=0;
while(sta[top]^x) tp[++res]=sta[top],insta[sta[top]]=0,top--;
tp[++res]=sta[top],insta[sta[top]]=0,top--;
for(int k=res;k>0;k--) q[j].push(tp[k]);
q[j].push(x);
}
else
if(x==s&&top)//特判J
{
int res=0;
while(top) tp[++res]=sta[top],insta[sta[top]]=0,top--;
for(int k=res;k>0;k--) q[j].push(tp[k]);
q[j].push(x);
}
else sta[++top]=x,insta[sta[top]]=true;
if(q[j].empty())
{
ans[j]=-i;
N--;
}
}
}
for(int i=1;i<=n;i++)
{
if(ans[i]) cout<<ans[i];
else cout<<q[i].size();
if(i^n) cout<<" ";
else puts("");
}
for(int i=1;i<=n;i++)
{
if(ans[i])
{
puts("");
ans[i]=0;//清零
continue;
}
while(!q[i].empty()) cout<<b[q[i].front()]<<" ",q[i].pop();
puts("");
}
}
return 0;
}