2012年成都Onsite (A,B,I,J,K)

本文深入探讨了高中概率题目的解决方法,通过解析一个具体例题展示了如何运用整数序列和对数运算进行简化计算。同时,文章详细介绍了使用DP(动态规划)算法解决枚举子树问题的步骤,包括枚举大小、分解问题以及优化计算过程。最后,文章以一个水BFS为例,阐述了解决此类问题的基本思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明出处,谢谢http://blog.youkuaiyun.com/ACM_cxlove?viewmode=contents    by---cxlove 

A:水题

B:高中概率知识 ,整出个式子,sigma( k*C(n+k,k)* (p^(n+1)*q^k+q^(n+1)*p^k)  )

然后就没有然后了,现场的时候是边乘边除乱搞过的,比较优越的是取个对数

double p1=log(p),p2=log(1-p);
double c=0,ans=0;
double s1=(n+1)*p1,s2=(n+1)*p2;
for(int i=0; i<=n; i++)
{
    ans+=(exp(c+s1)+exp(c+s2))*(n-i);
    c+=log(n+i+1)-log(i+1);
    s1+=p2;
    s2+=p1;
}


I:枚举子树的大小,DP

J:看成a*b*c<=n,(a<=b<=c) 那么a<=pow(n,1.0/3),b<=pow(n/a,1.0/2)

然后就枚举a,b,得出c的数量

注意可以调换顺序,分为三种情况

三个数相等,则不需要调换

有两个相等,3种

两两不等,6种

LL n;
int fuck1(LL n)
{
    int m=pow(n,0.5);
    if((LL)(m*m)>n) m--;
    if((LL)(1+m)*(m+1)<=n) m++;
    return m;
}
int fuck2(LL n)
{
    int m=pow(n,1.0/3);
    if((LL)(m*m*m)>n) m--;
    if((LL)(m+1)*(1+m)*(m+1)<=n) m++;
    return m;
}
int main()
{
    int cas=0;
    while(cin>>n)
    {
        int m=fuck2(n);
        LL ans=m;
        for(int i=1; i<=m; i++)
        {
            int k=fuck1(n/i);
            ans+=(n/i/i-i+k-i)*3;
            for(int j=i+1; j<=k; j++) ans+=6*(n/i/j-j);
        }
        cout<<"Case "<<++cas<<": "<<ans<<endl;
    }
    return 0;
}

K题:悲伤,其实就是个水BFS,不解释

int flag[10];
int n,k;
int vis[10005];
void bfs()
{
    mem(vis,0);
    queue<pair<string,int> >que;
    que.push(mp("",0));
    while(!que.empty())
    {
        pair<string,int>u=que.front();
        que.pop();
        for(int i=0;i<10;i++)
        {
            if(i==0&&u.second==0) continue;
            if(flag[i]) continue;
            pair<string,int>v=u;
            v.first+=(char)(i+'0');
            v.second=(v.second*10+i)%n;
            if(v.second == 0) {cout<<v.first<<endl;return ;}
            if(vis[v.second]==0)
            {
                vis[v.second]=1;
                que.push(v);
            }
        }
    }
    printf("-1\n");
}
int main()
{
    int cas=0;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        mem(flag,0);
        for(int i=0;i<k;i++)
        {
            int m;
            scanf("%d",&m);
            flag[m]=1;
        }
        printf("Case %d: ",++cas);
        if(k==0){printf("%d\n",n);continue;}
        bfs();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值