码迷,mamicode.com
首页 > 编程语言 > 详细

neuoj1472 yuki的氪金之旅(倒置树状数组

时间:2019-09-25 01:10:42      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:fun   除法   pmi   flush   type   air   map   put   fwrite   

这题一直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;
}

 

neuoj1472 yuki的氪金之旅(倒置树状数组

标签:fun   除法   pmi   flush   type   air   map   put   fwrite   

原文地址:https://www.cnblogs.com/wzgg/p/11581986.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!