概率专题一(LightOJ - 1027 LightOJ - 1030 LightOJ - 1038 LightOJ - 1079)

题目链接:https://vjudge.ppsucxtt.cn/contest/76505#problem/A
题目:LightOJ - 1027
题目思路:

按照样例解释
3
-3 -6 -9
d=1/33+1/3(6+d)+1/3*(9+d)
化简得d=time(总时间)/(n-cnt)//cnt为负数的个数

代码:

#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 800000;
int test,cas=1;
int num[maxn];
int cnt;
int n;
int gcd(int a, int b) {
    return a == 0 ? b :  gcd(b % a, a);
}
void solve() {
    int t = 0;
    for(int i = 0; i < n; i++)
        t = t + (num[i] > 0 ? num[i] : -num[i]);
    int g = gcd((n - cnt), t);
   // cout<<(n-cnt)<<" "<<t<<endl;
    printf("%d/%d\n", t  / g, (n - cnt) / g);
}
int main()
{
    scanf("%d", &test);
    while(test--){
        scanf("%d", &n);
        cnt=0;
        for(int i=0;i<n;i++){
            scanf("%d", &num[i]);
            if(num[i]<0){
                cnt++;
            }
        }
        printf("Case %d: ", cas++);
        if(cnt==n){
            printf("inf\n");
            continue;
        }
        /*int sum=0;
        for(int i=1;i<=n;i++){
            sum+=abs(num[i]);
        }
        int g=gcd((n-cnt),sum);
        //cout<<(n-cnt)<<" "<<sum<<endl;
        printf("%d/%d\n",sum/g,(n-cnt)/g);*/
        solve();
    }
    return 0;
}

题目: LightOJ - 1030
题目思路:首先是肯定能到达的位置为开头和结尾,其次计算出到达每个位置得概率乘以相应位置黄金数量,得出结果
代码:

#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 800000;
int t;
int n;
int a[maxn];
double sum=0;
int cas=1;
double p[maxn];
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sum=0.0;
        memset(p,0,sizeof(p));
        if(n!=1)sum+=(a[1]+a[n]);
        else sum+=a[1];
        p[1]=1;
        for(int i=1;i<n;i++){
            int d=n-i;
            if(d<6){
                double k=1.0/(d*1.0);
                for(int j=1;j<=d;j++){
                    p[i+j]+=p[i]*k;
                }
            }else{
                double k=1.0/6;
                for(int j=1;j<=6;j++){
                    p[i+j]+=p[i]*k;
                }
            }
        }
        for(int i=2;i<n;i++){
            sum+=p[i]*a[i];
        }
        //printf("Case %d: %.6f\n",++cas,sum);
        printf("Case %d: %.6f\n", cas++, sum);
    }
    return 0;
}

题目:LightOJ - 1038
题目思路:由下而上进行递推计算,主要是加上自身得情况
参考链接:https://blog.csdn.net/guagua_de_xiaohai/article/details/87536131
代码:

#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn =1e5+10;
int t;
int n;
double dp[maxn];
void init(){
    dp[1]=0.0;
    for(int i=2;i<=maxn;i++){
        dp[i]=0.0;
        int cnt=0;
        for(int j=1;j*j<=i;j++){
            if(i%j==0&&(i/j)!=j){
                cnt+=2;
                dp[i]+=2+dp[j]+dp[i/j];
            }
            if(j*j==i){
                cnt++;
                dp[i]+=dp[j]+1;
            }
        }
        dp[i]/=(cnt-1);//处理自身情况
    }
}
int main()
{
    init();
    scanf("%d",&t);
    int cas=0;
    while(t--){
        scanf("%d",&n);
        printf("Case %d: %.7lf\n",++cas,dp[n]);
    }
    return 0;
}

题目:LightOJ - 1079
题目思路:01背包问题,通过计算逃跑的概率,因为要抢多家银行,自然是计算能逃出得概率,同时逃出得概率相互独立,即抢i和j两家银行逃出的概率为(1-p[i])*(1-p[j]),通过dp[j],即为抢劫j钱后逃出得概率来逆推出结果
代码:

#include<iostream>
#include<cstring>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn =100*100+100;
int t,cas;
int n;
int v[maxn];
double dp[maxn],p[maxn],P;
int sum=0;
int main()
{
    cas=1;
    scanf("%d",&t);
    while(t--){
        memset(dp,0.0,sizeof(dp));
        scanf("%lf%d",&P,&n);
        for(int i=1;i<=n;i++){
            scanf("%d%lf",&v[i],&p[i]);
            sum+=v[i];
        }
        dp[0]=1.0;
        for(int i=1;i<=n;i++){
            for(int j=sum;j>=v[i];j--){
                dp[j]=max(dp[j],dp[j-v[i]]*(1-p[i]));
            }
        }//01背包
        for(int i=sum;i>=0;i--){//逆推
            if(dp[i]>=(1-P)){
                printf("Case %d: %d\n",cas++,i);
                break;
            }
        }
        sum=0;
    }
    return 0;
}
上一篇:Halloween Costumes LightOJ - 1422


下一篇:LightOJ - 1364 Expected Cards(概率dp)