[Vijos]1266 搜集环盖*增强版 解题报告

本文提供了一种高效求解概率论问题的方法,通过使用素数分解避免了超时问题,并实现了高精度计算。代码示例涵盖了从初始化到最终输出的完整过程,适合对概率论和大数法则感兴趣的学习者。

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

P1266 搜集环盖 -Vijos

<object width="450" height="500" align="middle" id="reader" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"><param value="window" name="wmode"><param value="true" name="allowfullscreen"><param name="allowscriptaccess" value="always"><param value="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&docid=56147518a8114431b90dd81e&title=%E6%9C%89%E5%85%B3%E6%A6%82%E7%8E%87%E5%92%8C%E6%9C%9F%E6%9C%9B%E9%97%AE%E9%A2%98%E7%9A%84%E7%A0%94%E7%A9%B6&doctype=doc&fpn=5&npn=5&readertype=external&catal=0&cdnurl=http://txt.wenku.baidu.com/play" name="movie"><embed width="450" align="middle" height="500" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" name="reader" src="http://wenku.baidu.com/static/flash/apireader.swf?docurl=http://wenku.baidu.com/play&docid=56147518a8114431b90dd81e&title=%E6%9C%89%E5%85%B3%E6%A6%82%E7%8E%87%E5%92%8C%E6%9C%9F%E6%9C%9B%E9%97%AE%E9%A2%98%E7%9A%84%E7%A0%94%E7%A9%B6&doctype=doc&fpn=5&npn=5&readertype=external&catal=0&cdnurl=http://txt.wenku.baidu.com/play" wmode="window" allowscriptaccess="always" bgcolor="#FFFFFF" ver="9.0.0" allowfullscreen="true"></embed></object>


 

概率论+高精度

约分时用素数分解,否则超时

/*
Programmed By Lixiang
Copyright (c) Lixiang. 2014~2019  All rights received.
Vijos 1266
*/
#include<stdio.h>
#include<cstring>
//#include<windows.h>
const int maxl=480,mod=1000000;
int prime[1001],pnum;
bool isPrime[1001];
inline int max(int a,int b){return a>b?a:b;}
/*------------------------------------------I am the divided line------------------------------------------*/
struct bignum{
    int num[maxl];
	int len,bit;
    void add(struct bignum a){
        len=max(len,a.len);
        for(int i=1;i<=len;i++){
          num[i]=num[i]+a.num[i];
		  if(num[i]>mod)num[i]-=mod,num[i+1]++;
		}
		if(num[len+1])len++;
        return;
    }
    void minus(struct bignum a){
      for(int i=1;i<=len;i++){
        if(a.len<i)break;
        if(num[i]<a.num[i])num[i]+=mod,num[i+1]--;
        num[i]-=a.num[i];
      }
      while(num[len]==0)len--;
    }
    void mult(int k){
      int bit=0;
      for(int i=1;i<=len;i++){
        int x=num[i];x=x*k+bit;
        bit=x/mod;
        num[i]=x%mod;
      }
      while(bit)num[++len]=bit%mod,bit/=mod;
    }
    void div_div(int k){
      int bit=0;
      for(int i=len;i>=1;i--){
        int x=num[i]+bit;
        bit=x%k*mod;
        num[i]=x/k;
      }
      while(num[len]==0)len--;
    }
	int comp(struct bignum a){
		if(len>a.len)return 1;
		if(len<a.len)return -1;
		if(len==a.len){
		  for(int i=len;i>=1;i--){
			if(num[i]>a.num[i])return 1;
			if(num[i]<a.num[i])return -1;
		  }
		}
		return 0;
	}
    bool isDivided(int k){
      int bit=0;
      for(int i=len;i>=1;i--){
        int x=num[i]+bit;
        bit=x%k*mod;
      }	
      if(bit!=0)return 0;
      else return 1;
    }
    void count(){
    	bit=6*(len-1);
    	if(num[len]>=100000)bit+=6;
    	else if(num[len]>=10000)bit+=5;
    	else if(num[len]>=1000)bit+=4;
    	else if(num[len]>=100)bit+=3;
    	else if(num[len]>=10)bit+=2;
    	else bit+=1;
    }
    void print(){
      printf("%d",num[len]);
      for(int i=len-1;i>=1;i--)printf("%06d",num[i]);
    }
}tmp;
/*------------------------------------------I am the divided line------------------------------------------*/
bignum equal_div(struct bignum a,int k){
    bignum b;b.len=a.len;
    memset(b.num,0,sizeof(b.num));
    int bit=0;
    for(int i=a.len;i>=1;i--){
      int x=a.num[i]+bit;
      bit=x%k*mod;
      b.num[i]=x/k;
    }
    while(b.num[b.len]==0)b.len--;
    return b;
}
/*------------------------------------------I am the divided line------------------------------------------*/
struct SearchCap{
	struct bignum one,fir,sec,thi,mot,son;
	int N;
	void findPrime(){
		//float a=GetTickCount();
		prime[++pnum]=2;
		for(int i=3;i<=999;i+=2){
		  if(isPrime[i])continue;
		  for(int j=i*i;j<=999;j+=i)isPrime[j]=1;
		  prime[++pnum]=i;
		}
		//printf("Module Get-Prime has finished.Total Time:%.0fms\n",GetTickCount()-a);
	}
	void init(){
		scanf("%d",&N);one.num[1]=1;one.len=1;
		fir.num[1]=0;fir.len=1;sec.num[1]=0;sec.len=1;thi.num[1]=0;thi.len=1;
		mot.num[1]=1;mot.len=1;son.num[1]=0;son.len=1;
		
	}
	void work(){
		//float a=GetTickCount();
		for(int i=2;i<=N;i++)mot.mult(i);
		tmp=equal_div(mot,2);
		for(int i=1;i<=N;i++)son.add(equal_div(mot,i));
		mot.div_div(N);
		//printf("Module factorial has finished.Total Time:%.0fms\n",GetTickCount()-a);
		//a=GetTickCount();
		while(son.comp(mot)==1)son.minus(mot),fir.add(one);
		//printf("Module reduction I has finished.Total Time:%.0fms\n",GetTickCount()-a);
		//a=GetTickCount();
		for(int i=1;i<=pnum;i++){
			int k=prime[i];
			while(son.isDivided(k)&&mot.isDivided(k)){
				son.div_div(k);
				mot.div_div(k);
			}
		}
		//printf("Module reduction II has finished.Total Time:%.0fms\n",GetTickCount()-a);
		if(son.comp(mot)==0)fir.add(one),fir.print(),putchar('\n');
		else{
			fir.count();mot.count();
			for(int i=1;i<=fir.bit;i++)putchar(' ');
			son.print();putchar('\n');
			fir.print();
			for(int i=1;i<=mot.bit;i++)putchar('-');putchar('\n');
			for(int i=1;i<=fir.bit;i++)putchar(' ');
			mot.print();putchar('\n');
		}
	}
}sol;
/*------------------------------------------I am the divided line------------------------------------------*/
int main(){
	sol.findPrime();
	sol.init();
	//float a=GetTickCount();
	sol.work();
	//printf("Main Function has finished.Total Time:%.0fms\n",GetTickCount()-a);
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值