对于这道傻题.........我考场上退了一个多小时才推出来这个东西是排列...........然后我打的dfs效率n!logInf正好n=9是最后一个能过的数结果前三个点的n全是10,然后这题全场爆零.........
我在考场上试了很多种方法发现只有排列可以对样例........解释一下为什么,一个数自己对自己的位置造成影响的只有最后一次操作,而这些数的最后一次操作在时间轴上形成了排列,最终造成了最后那一堆书的排列,而他们每一种排列的概率也就是每一种最后一位结束顺序的概率,就会趋近于我们平常正常求A所求出来的概率,所以我就枚举了每一种A.......
正解:我们不把状态按排列分开,而是把最终答案分为每一个数对他的贡献,那么每一个数的贡献就是最终排在他前面的数的个数的期望+1,而最终排在他前面的数的个数的期望就是除他以外的其他数每一个数排在他前面的概率加和,假设我们研(一声)究(一声)一下j在i前面的概率我们发现对所有A,j排在i前面占pi/(pi+pj)那么我们就可以开心的O(n*n*loginf)求解了
友情提示:对于一开始给出的a b我们一开始求逆元即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long LL; const LL N=1010; const LL P=1000000007; inline void read(LL &sum){ register char ch=getchar(); for(sum=0;ch<'0'||ch>'9';ch=getchar()); for(;ch>='0'&&ch<='9';sum=(sum<<1)+(sum<<3)+ch-'0',ch=getchar()); } LL n,p[N]; inline LL Pow(LL x,LL y){ LL ret=1; while(y){ if(y&1)ret=ret*x%P; y>>=1,x=x*x%P; } return ret; } int main(){ read(n); for(int i=1;i<=n;i++){ LL a,b; read(a),read(b); p[i]=a*Pow(b,P-2)%P; } LL ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(j!=i) ans=(ans+p[i]*p[j]%P*Pow((p[i]+p[j])%P,P-2)%P)%P; ans=ans+1; ans%+P; printf("%lld",ans); }