首先说明这次Test Round,非常痛心,一题都没做出来(不,是做出A题来了,没开long long,导致WA了将近十发)
正如某句话所言:“不开long long 见祖宗”,以后我统一开long long,在从这个地方发生严重错误我倒立吃xx
话不多说,写题解(放个链接:momo)
先贴张图片上来水一水
题目大意:给出n个数,a和b,a和b的作用作为排序循环的条件,问你,给出任意n个数的数组和随意的a,b,能否保证排序算法是正确的(即运行完数组有序)
题解:很显然,只需要看最后的那个数能否移到最前面来即可,有a轮循环,每轮循环可以排序b-1个数,从最后排到最前需要移动n-1个数,方案即: a*(b-1) >= n?"Yes":"No"
顺便贴一下没开long long导致WA的代码,都怪自己没算范围
失败失败呐害
老规矩,贴图
题目大意:给出n个帽子,初始的时候有一只兔子在第一个魔术帽里,然后给出总操作数m,但小沃沃只看到k次操作,然后输入k行,每行有op,x,y三个参数,代表看到的第几次操作,交换(x,y),然后问你每个魔术帽有兔子的概率。
题解:很容易想到,只有两种不同结果,具体看到兔子转移了魔术帽的概率和其他魔术帽的概率。
1.不被选中当前魔术帽的概率:C(2,n-1)/C(2,n) = (n-1)(n-2)/(n)(n-1)[上下约分] = (n-2)/n
2.那么选中当前魔术帽的概率则为:1-(未选中魔术帽的概率) = 1-(n-2)/n = n/n - (n-2)/n = 2/n
用p代表选中兔子的概率
则没有兔子概率为:(1-p)*1/(n-1), 1/(n-1)代表除去有兔子那个魔术帽的每个帽子概率
那么有兔子概率为:p(*1)[因为只有这个选中,所以是1/1=1,省略不写)]
整体运算则为:
两个魔术帽: 选中一个魔术帽的概率*这个魔术帽没有兔子的概率 + 选中另一个魔术帽的概率*有兔子的概率
2/n*(1-p)*(1/n-1) + (n-2)/n*p
除法意义下取模,则用逆元,费马小定理 x/y = x*pow2(y,mod-2),其中pow2是快速幂
完整代码为:
#include
using namespace std;
#define ll long long
const ll mod = 998244353;
ll pow2(ll a,ll n){
ll res = 1;
while(n){
if(n&1) res = (res*a)%mod;
a = (a*a)%mod;
n >>= 1;
}
return res;
}
struct node{
ll id,l,r;
}a[100100];
int T;
ll n,m,k;
void solve(){
memset(a,0,sizeof(a));
cin>>n>>m>>k;
for(int i = 1;i<=k;++i){
ll op,x,y;
cin>>op>>x>>y;
a[i] = (node){op,x,y};
}
ll sum1 = pow2(n,mod-2),sum2 = pow2(n-1,mod-2);
ll pos = 1,ans1 = 1,ans2 = 0,cnt = 1;
for(int i = 1;i<=m;++i){
/* 标记能看到具体兔子转移的某个魔术帽 */
if(a[cnt].id == i && cnt <= k){
if(a[cnt].l == pos) pos = a[cnt].r;
else if(a[cnt].r == pos) pos = a[cnt].l;
++cnt;
}else{
/* ans1 ans2 代表(初始有兔子魔术帽的和无兔子魔术帽)概率p,表示有兔子的概率,初始是只有1才有,其余全为0*/
/*
1.不被选中当前魔术帽的概率:C(2,n-1)/C(2,n) = (n-1)(n-2)/(n)(n-1)[上下约分] = (n-2)/n
2.那么选中当前魔术帽的概率则为:1-(未选中魔术帽的概率) = 1-(n-2)/n = n/n - (n-2)/n = 2/n
3.p为选中兔子概率,没有兔子概率为:(1-p)*1/(n-1),1/(n-1)代表除了有兔子那个魔术帽的概率
4.p为选中兔子概率,有兔子概率为:2/n*p(*1因为只有这个选中,所以是1/1=1,省略不写)
*/
/*
整体运算:
两个魔术帽: 选中一个魔术帽的概率*这个魔术帽没有兔子的概率 + 选中另一个魔术帽的概率*有兔子的概率
整体式子则为: 2/n*(1-p)*(1/n-1) + (n-2)/n*p
除法意义下取模,则用逆元,费马小定理 x/y = x*pow2(y,mod-2),其中pow2是快速幂
*/
ans1 = (((((2*sum1)%mod*sum2)%mod) * ((1-ans1+mod)%mod))%mod)+((((n-2)*sum1)%mod)*ans1)%mod;
ans1%=mod;
ans2 = (((((2*sum1)%mod*sum2)%mod) * ((1-ans2+mod)%mod))%mod)+((((n-2)*sum1)%mod)*ans2)%mod;
ans2%=mod;
}
}
for(int i = 1;i<=n;++i){
if(i == pos) cout<<ans1<<" ";
else cout<<ans2<<" ";
}
cout<<endl;
}
int main(void){
scanf("%d",&T);
while(T--){
solve();
}
return 0;
}
当然啦,官方题解可是用了线段树(反正我是没想到还能这样解,我太菜了)
线段树题解等等补(要是问等等是多久,可能明天,后天,大后天,先鸽一会?)