【组合数学】LGP3330(ZJOI2011)+UOJ#209
来源:互联网 发布:星际争霸2 剧情知乎 编辑:程序博客网 时间:2024/06/07 05:31
LGP3330 看电影(MOVIE)
原题地址
【题目大意】
一共有n个人,k个格子(格子标号为1~k)
循环n轮,每轮随机一个k以内的整数(设为m),若m~k这些格子里有空的,就把一个人放到格子里,否则这个人将站着。
问全部人都坐着的概率是多少。
【题目分析】
一眼组合数学,实在不会可以考虑打表。
组合数学中经典的古典概型,概率等于合法的方案数除以总方案数。
【解题思路】
我们易得总方案数=
合法方案数的计算:考虑在最后面加一个座位,然后所有的座位连成一个环。
这样我们保证不论怎么放,最后都会有一个空的位置,那么我们从这个空的位置断开(将它丢到),必然是一个合法的情况。
现在那么总方案数等于
综上所述,答案就是:
(K+1)N−1×(N−K+1)KN
要用高精度 。
【代码】
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=205;const int MAXL=505;int prinum,T,n,k,len;int a[MAXL],pri[MAXN],ans[MAXN],ans2[MAXN];int p[MAXN][MAXN];bool ispri[MAXN];inline void get_prime(){ memset(ispri,true,sizeof(ispri)); ispri[1]=false; for(int i=2;i<MAXN;++i) { if(ispri[i]) { ++prinum; pri[prinum]=i; } for(int j=1;j<=prinum && pri[j]*i<MAXN;++j) { ispri[pri[j]*i]=false; if(i%pri[j]==0) break; } }}inline void get_num(){ int x; for(int i=1;i<MAXN;++i) { x=i; for(int j=1;j<=prinum;++j) while(x%pri[j]==0) { p[i][pri[j]]++; x/=pri[j]; } }}inline void _reset(){ memset(ans,0,sizeof(ans)); memset(ans2,0,sizeof(ans2));}inline void mul(int x){ if(len==0) { len=1;a[len]=x; for(len++;a[len];) { a[len+1]+=a[len]/10; a[len++]%=10; } --len; } else { for(int i=1;i<=len;++i) a[i]*=x; for(int i=1;i<=len;++i) { a[i+1]+=a[i]/10; a[i]%=10; } for(len++;a[len];) { a[len+1]+=a[len]/10; a[len++]%=10; } --len; }}inline void get_ans(){ /* for(int i=1;i<10;++i) printf("%d ",ans[i]); printf("\n"); for(int i=1;i<10;++i) printf("%d ",ans2[i]); printf("\n");*/ len=0; memset(a,0,sizeof(a)); for(int i=1;i<MAXN;++i) for(int j=1;j<=ans[i];++j) mul(i); if(!len) printf("1"); for(int i=len;i;--i) printf("%d",a[i]); printf(" "); len=0; memset(a,0,sizeof(a)); for(int i=1;i<MAXN;++i) for(int j=1;j<=ans2[i];++j) mul(i); if(!len) printf("1"); for(int i=len;i;--i) printf("%d",a[i]); printf("\n");}inline void solve(){ scanf("%d%d",&n,&k); if(n>k) { printf("0 1\n"); return; } for(int i=1;i<=k+1;++i) ans[i]=p[k+1][i]*(n-1); if(k-n>0) for(int i=1;i<=k-n+1;++i) ans[i]+=p[k-n+1][i]; if(k>1) for(int i=1;i<=k;++i) { ans2[i]=p[k][i]*n-ans[i]; ans[i]-=p[k][i]*n; } get_ans();}int main(){ freopen("LGP3330.in","r",stdin); freopen("LGP3330.out","w",stdout); get_prime(); get_num(); scanf("%d",&T); while(T--) { _reset(); solve(); } return 0;}
UOJ#209. 【UER #6】票数统计
原题地址
【题目大意】
一共有n个数字 ,每个数字要么是0,要么是1。
有m个限制
求满足所有限制的序列个数。
【题目分析】
都是骗人的!
【解题思路】
当x!=y的时候,我们已经确定了这个限制是对前缀还是后缀的。
当x=y的时候,我们只需要保留最大的那个x就行了。
然后,一波组合数学。
答案是x=y是前缀限制的个数+后缀限制的个数-前后缀都限制的个数。
那么,现在就是有一堆前后缀的限制,让你求方案数。
如果只有前缀或只有后缀就是一个划分成m个区间的组合数学。
如果两个都有就把前缀转成后缀或者把后缀转成前缀。
枚举1的总和就行了。
【代码】
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int MAXN=5010;const int mod=998244353;int n,m,ans,tot,lz,T;int C[MAXN][MAXN];struct Tnode{ int x,y,bz,ty; Tnode(){} Tnode(int xx,int yy,int bzz,int tyy) { x=xx;y=yy; bz=bzz;ty=tyy; }};Tnode a[MAXN],p[MAXN];inline void get_C(){ C[0][0]=1; for(int i=1;i<MAXN-5;++i) { C[i][0]=1; for(int j=1;j<=i;++j) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; }}inline bool cmp(Tnode A,Tnode B){ return A.x<B.x;}inline void init(){ scanf("%d%d",&n,&m); tot=ans=lz=0; for(int i=1;i<=m;++i) { int x,y; scanf("%d%d",&x,&y); if(x>y) a[++tot]=(Tnode){x,y,0,0}; else if(x<y) a[++tot]=(Tnode){n-y,x,1,0}; else lz=max(lz,x); } a[++tot]=(Tnode){lz,lz,0,1}; a[++tot]=(Tnode){n-lz,lz,1,2}; sort(a+1,a+tot+1,cmp);// for(int i=1;i<=tot;++i)// printf("%d %d %d %d\n",a[i].x,a[i].y,a[i].bz,a[i].ty);}inline void solve(){ for(int typ=1;typ<=3;++typ) { for(int i=1;i<=n;++i) { int cnt=0;bool flag=true; for(int j=1;j<=tot;++j) { if(a[j].ty==typ) continue; p[++cnt].x=a[j].x; if(a[j].bz) p[cnt].y=i-a[j].y; else p[cnt].y=a[j].y; if(p[cnt].y<0 || p[cnt].y>i) { flag=false; break; } if(p[cnt].x<p[cnt].y) { flag=false; break; } if(p[cnt].x-p[cnt-1].x<p[cnt].y-p[cnt-1].y) { flag=false; break; } if(p[cnt].y-p[cnt-1].y<0) { flag=false; break; } } if(!flag) continue; int sum=1; for(int j=1;j<=cnt;++j) sum=1ll*sum*C[p[j].x-p[j-1].x][p[j].y-p[j-1].y]%mod; sum=1ll*sum*C[n-p[cnt].x][i-p[cnt].y]%mod;// printf("sum:%d\n",sum); if(typ<=2) ans=(ans+sum)%mod; else ans=(ans-sum+mod)%mod; } } printf("%d\n",ans);}int main(){// freopen("UOJ209.in","r",stdin);// freopen("UOJ209.out","w",stdout); get_C(); scanf("%d",&T); while(T--) { init(); solve(); } return 0;}
- 【组合数学】LGP3330(ZJOI2011)+UOJ#209
- [组合数学] BZOJ 2227 [Zjoi2011]看电影(movie)
- [UOJ#74][UR #6]破解密码(数学相关)
- [UOJ#206][Apio2016]Gap(分块+数学相关)
- HDOJ2045(组合数学)
- Combinations(组合数学)
- 求组合数(数学)
- POJ 1715(组合数学)
- hdu4945(dp+组合数学)
- HDU4908BestCoder Sequence(组合数学)
- Catalan数(组合数学)
- ZOJ-3791(组合数学)
- (组合数学)Stirling 数
- HDOJ-3037(组合数学)
- Lightoj 1058 (组合数学)
- hysbz1008 越狱(组合数学)
- 吃糖果(组合数学)
- POJ3731 Escape(组合数学)
- [BZOJ]2555 Substring 后缀自动机&LCT
- 大数取模
- 孔蒙蒙我爱你
- 欢迎使用CSDN-markdown编辑器
- 带儿子去华侨城大剧院看了《金面王朝》儿子看嗨了
- 【组合数学】LGP3330(ZJOI2011)+UOJ#209
- 用抽象类来模拟动物的叫声
- 如何连接一个Linux服务器
- linux系统运维必会
- SQL Server非常有用的资料
- 尝试Java加锁新思路:原子变量和非阻塞同步算法
- 第4章 学习Shader所需的数学基础(下)(坐标空间及其变换)
- 算法的一些小栗子2(选择排序)
- 谈一谈Go的Map的使用用法