算法竞赛入门10.2计数与概率基础例题代码

23 篇文章 0 订阅
11 篇文章 0 订阅

10.6 Irrelevant Elements UVA1635


思路:基础组合计数


#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
const int N = 1e5+5;
using namespace std;
long long C[N][20];
int prime[20][2];
inline  int judge(int x,int m,int k)
{
    int res = 0;
    while(x%m==0){
        res+=k;
        x/=m;
    }return res ;
}
inline int work(int n,int m,int num)
{
    memset(C,0,sizeof(C));
    int ans = 0;
    for(int i=1;i<=n;i++)
    {
        int k=0;
        for(int j=0;j<num;j++){
            C[i][j]=C[i-1][j]+judge(n-i+1,prime[j][0],1)+judge(i,prime[j][0],-1);
            if(C[i][j]>=prime[j][1])k++;
        }
        if(k==num){
            C[i][num]=1;
            ans++;
        }
    }return ans ;
}

inline int init(int x){
    int m = sqrt(x+0.5);
    int primenum = 0;
    for(int i=2;i<=m;i++){
        while(x%i==0){
            if(!primenum||prime[primenum-1][0]!=i){
                prime[primenum][0]=i;
                prime[primenum++][1]=1;
            }else {
                prime[primenum-1][1]++;
            }x/=i;
        }
    }if(x!=1){
        prime[primenum][0]=x;
        prime[primenum++][1]=1;
    }return primenum ;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
    {
        int primenum=init(m);
        int ans = work(n-1,m,primenum);
        printf("%d\n",ans);
        if(ans==0){
            printf("\n");
            continue;
        }
        for(int i=0;i<n;i++){//printf("%lld ",C[i]);
            if(C[i][primenum]>0)printf("%d%c",i+1,(--ans)?' ':'\n');
        }
    }
    return 0;
}


10.7 Send a Table UVA10820


思路:1~n 的欧拉值 复杂度O(nloglogn)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 50000+5;
int phi[N];


inline void phi_table (int n){
    memset(phi,0,sizeof(phi));
    phi[1]=1;
    for(int i=2;i<=n;i++) if(!phi[i]){
        for(int j=i;j<=n;j+=i){
            if(!phi[j])phi[j]=j;
            phi[j] = phi[j]/i*(i-1);
        }
    }
}

int main()
{
    int n;
    while(scanf("%d",&n)==1&&n)
    {
        phi_table(n);
        long long ans = 1;
        for(int i=2;i<=n;i++)
            ans += phi[i]*2;
        printf("%lld\n",ans);
    }
}


10.9 Headshot UVA1636


思路:条件概率

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

char str[105];

int main()
{
    while(gets(str)!=NULL)
    {
        int n=strlen(str);
        int num1=0,num2=0;
        for(int i=0;i<n;i++)
        {
            if(i!=n-1&&str[i]=='0'&&str[i+1]=='1')
                num1++;
            if(i==n-1&&str[i]=='0'&&str[0]=='1')
                num1++;
            if(str[i]=='1')

                num2++;
        }
        int  p1=num1*(n-1),p2=(n-num2)*num2;
        if(p1<p2)
            printf("SHOOT\n");

        else if(p1>p2)
            printf("ROTATE\n");
        else
            printf("EQUAL\n");
    }
    return 0;
}


10.10 Cows and Cars UVA10491


思路:全概率公式

#include<cstdio>
#include<algorithm>
using namespace std;


int main()
{
    int a,b,c;
    while(scanf("%d%d%d",&a,&b,&c)==3)
    {
        double ans=(b*b-b+a*b)/((a+b)*(a+b-c-1));
        printf("%.2f\n",ans);
    }
}


10.11 Probability|Given UVA11181


思路:全概率+条件概率

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>


using namespace std;
double e[1100000];
int n,m;
double p[25];
double ans[25];
vector<int>A[21];

inline void oper(int x){
    int cur = 0,y=x;
    while(x){
        cur += x%2;
        x>>=1;
    }A[cur].push_back(y);
}

inline void init()
{
    for(int x=1;x<1100000;x++){
        oper(x);
    }
}

inline double work(int x)
{
    double res = 1;
    for(int i=0,tem=1;i<n;tem<<=1,i++){
        if(x&tem) res*=p[i];
        else res*=(1-p[i]);
    }for(int i=0,tem=1;i<n;tem<<=1,i++){
        if(x&tem) ans[i]+=res;
    }return res;
}

int main()
{
    int t=0;init();
    while(scanf("%d%d",&n,&m)==2)
    {
        if(!n&&!m)break;




        memset(ans,0,sizeof(ans));
        for(int i=0;i<n;i++)
        {
            scanf("%lf",&p[i]);
        }double sum = 0;
        printf("Case %d:\n",++t);

        if(m==0){
            for(int i=0;i<n;i++)
                printf("0.000000\n");
            continue;
        }
        for(int i=0;i<A[m].size()&&A[m][i]<(1<<n);i++)
        {
            //printf("x = %d\n",A[m][i]);
            sum += work(A[m][i]);
        }
        for(int i=0;i<n;i++)
            printf("%.6f\n",ans[i]/sum);
    }
}


10.12 Double Patience UVA1637


思路:状压记忆化搜索  九位5进制表示牌堆的状态进行记忆化搜索或者用九维数组进行dp都行


#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>

const int Max = 1953124;
using namespace std;
bool vis[Max+5];
char card[10][5][3];
double  step[Max+5];



inline void oper(int *now,int x){
    for(int i=0;i<9;i++){
        now[i] = x%5;
        x/=5;
    }
}


inline int get_id(int *now,int a,int b){
    int res = 0 ;
    for(int i=8;i>=0;i--)
    {
        res = res*5 + now[i];
        if(i==a||i==b)res--;
    }

    return res ;
}


inline double dfs(int x)
{
//printf("x=%d\n",x);
//if(x==0)system("pause");
    if(vis[x])return step[x];
    vis[x] = true;
    int now[10];
    oper(now,x);
    int cur = 0;
    for(int i=0;i<9;i++)
    {
        for(int j=i+1;j<9;j++)
        {
            if( now[i] && now[j] && card[i][now[i]][0] == card[j][now[j]][0] )
            {

                int id = get_id(now,i,j);
                step[x] += dfs(id);
                cur++;

                //system("pause");
            }
        }
    }
    if( cur ) step[x] /= cur;

    return step[x];
}

int main()
{
    while(scanf("%s %s %s %s",card[0][1],card[0][2],card[0][3],card[0][4]) == 4 )
    {
        for(int i=1;i<9;i++)
            for(int j=1;j<=4;j++)
                scanf("%s",card[i][j]);
        memset(step,0,sizeof(step));
        memset(vis,0,sizeof(vis));
        step[0]=1.0;vis[0]=true;
        double ans = dfs(Max);
        printf("%.6f\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值