neuoj1472 yuki的氪金之旅(倒置树状数组
这题一直re不造为啥。。后来yww大神把树状数组“倒过来”就过了,倒过来的好处是算sum(d[i]+1)就行,不涉及除法,不用求逆元。
题意:初始手牌颜值是0,一共抽卡n次,第i次抽卡有pi的概率能抽到颜值为di的卡,若di>当前手牌颜值,则替换,最后问改变手牌次数的期望。
做法:树状数组维护前缀概率积。先把di离散化,di作为下标,pi作为值,逆元用费马小定理那个推论,本质就是求每次改变手牌的概率,第i次就是pi(1-pj)(1-pk)...(其中j,k<i),即p[i]*sum(d[i]+1)。
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<ctime> #include<functional> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<stack> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef double db; typedef long double ldb; typedef pair<int,int> pii; typedef pair<ll,ll> pll; void open(const char *s){ #ifndef ONLINE_JUDGE char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout); #endif } void open2(const char *s){ #ifdef DEBUG char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout); #endif } template <class T> int upmin(T &a, const T &b){return (b<a?a=b,1:0);} template <class T> int upmax(T &a, const T &b){return (b>a?a=b,1:0);} namespace io { const int SIZE=(1<<20)+1; char ibuf[SIZE],*iS,*iT; char obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1; int getc() { (iS==iT?iS=ibuf,iT=ibuf+fread(ibuf,1,SIZE,stdin):0); return iS==iT?EOF:*(iS++); } int f; char c; template <class T> void get(T &x) { f=1; for(c=getc();(c<'0'||c>'9')&&c!='-';c=getc()); (c=='-'?f=-1,c=getc():0); x=0; for(;c>='0'&&c<='9';c=getc()) x=x*10+c-'0'; x*=f; } void flush() { fwrite(obuf,1,oS-obuf,stdout); oS=obuf; } void putc(char x) { *(oS++)=x; if(oS==oT) flush(); } int a[55],t; template <class T> void put(T x) { if(!x) putc('0'); x<0?putc('-'),x=-x:0; while(x) { a[++t]=x%10; x/=10; } while(t) putc(a[t--]+'0'); } void space() { putc(' '); } void enter() { putc('\n'); } struct flusher { ~flusher() { flush(); } } io_flusher; } const int infi=0x3fffffff; const ll infll=0x3fffffffffffffffll; const int N=100010; const ll p=1000000007; ll fp(ll a,ll b) { ll s=1; for(;b;b>>=1,a=a*a%p) if(b&1) s=s*a%p; return s; } const ll inv100=fp(100,p-2); ll a[N],d[N]; int b[N],c[N]; int n,t; void add(int x,ll v) { for(;x;x-=x&-x) d[x]=d[x]*v%p; } ll sum(int x) { ll res=1; for(;x<=t;x+=x&-x) res=res*d[x]%p; return res; } void solve() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld%d",&a[i],&b[i]); a[i]=a[i]*inv100%p; c[i]=b[i]; } sort(c+1,c+n+1); t=unique(c+1,c+n+1)-c-1; for(int i=1;i<=n;i++) b[i]=lower_bound(c+1,c+t+1,b[i])-c; for(int i=1;i<=n;i++) d[i]=1; ll ans=0; for(int i=1;i<=n;i++) { ans=(ans+a[i]*sum(b[i]+1))%p; add(b[i],1-a[i]); } ans=(ans%p+p)%p; printf("%lld\n",ans); } int main() { int t; scanf("%d",&t); while(t--) solve(); return 0; }