zoukankan      html  css  js  c++  java
  • [ZJOI2011]看电影(组合数学,高精度)

    [ZJOI2011]看电影

    这题模型转化很巧妙.(神仙题)

    对于这种题首先肯定知道答案就是合法方案除以总方案.

    总方案显然是(k^n).

    那么考虑怎么算合法方案.

    (n>k)的时候显然答案为0.

    否则,我们不妨虚构出来一个从最后一个座位到第一个座位传送门,如果一个人他走到最后一个座位还没有空位置的话,他本来应该要是站着的,但是现在有了传送门,他就可以走到第一个座位,再一路走看看有没有空座位,找个位置坐下,由于这样构成了一个环,座位的个数一定是够坐的.这样每个人都有座位了.

    我们现在要求的就是没有人穿过传送门的方案总数.考虑上面这样处理不好算.不妨再虚构一个座位,它的编号为(k+1),现在如果有人走到n没有座位,就会先坐在(n+1),那么一个不合法方案当且仅当(k+1)位置被人坐了,一个合法方案当且仅当(k+1)位置没有人坐.

    这样的圆排列一共有(frac{(k+1)^n}{k+1}=(k+1)^{n-1})(n个人,每个人可以选择(k+1)个座位中的一个坐下,有人就按照规则往后坐就可以了,反正可以坐下),只有(k-n+1)个位置是空的,我们可以选择从这些位置断环成链,并把这些位置当做(k+1)号座位.

    于是答案就是

    [frac{(k+1)^{n-1}(k-n+1)}{k^n} ]

    数据范围这么小是因为要高精...

    处理gcd的时候注意(k+1)(k)是没有公因子的,只要考虑(k-n+1)(k^n)的gcd.

    只要高精乘法,快速幂一下就可以了.

    #include<bits/stdc++.h>
    #define maxn 505
    #define ll long long
    using namespace std;
    struct num
    {
    	int a[5005],len;
    	void init(ll x)
    		{
    			memset(a,0,sizeof(a));len=0;
    			while(x)a[++len]=x%10,x/=10;
    		}
    	num operator * (num x)
    		{
    			num res;res.init(0);
    			for(int i=1;i<=len;i++)
    			{
    				int carry=0;
    				for(int j=1,t;j<=x.len;j++)
    				{
    					t=res.a[i+j-1];
    					res.a[i+j-1]=(a[i]*x.a[j]+carry+res.a[i+j-1])%10;
    					carry=(a[i]*x.a[j]+carry+t)/10;
    				}
    				res.a[i+x.len]=carry;
    			}
    			res.len=len+x.len;
    			while(res.len>0&&!res.a[res.len])res.len--;
    			return res;
    		}
    	void print(){for(int i=len;i>=1;i--)printf("%d",a[i]);printf(" ");}
    }ans,K,N;
    ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}
    num ksm(num A,int k)
    {
    	num res;res.init(1);
    	while(k)
    	{
    		if(k&1)res=res*A;
    		A=A*A;k>>=1;
    	}
    	return res;
    }
    int main()
    {
    	int T;cin>>T;
    	while(T--)
    	{
    		int n,k,m;ll g=1,t;scanf("%d%d",&n,&k);m=n;t=1;
    		if(n>k){printf("0 1
    ");continue;}
    		while(m>0&&g<gcd(t*k,k-n+1)&&t*k>0)g=gcd(k-n+1,t*k),m--,t=t*k;
    		N.init((k-n+1)/g);K.init(k+1);ans=ksm(K,n-1);ans=ans*N;ans.print();
    		K.init(k);N.init(t/g);ans=ksm(K,m);ans=ans*N;ans.print();printf("
    ");
    	}
    	return 0;
    	}
    
    
  • 相关阅读:
    lintcode69- Binary Tree Level Order Traversal- easy
    lintcode378- Convert Binary Search Tree to Doubly Linked Lis- medium
    lintcode448- Inorder Successor in Binary Search Tree- medium
    lintcode94- Binary Tree Maximum Path Sum- medium
    lintcode475- Binary Tree Maximum Path Sum II- medium
    *lintcode246- Binary Tree Path Sum II- easy
    lintcode376- Binary Tree Path Sum- easy
    lintcode619- Binary Tree Longest Consecutive Sequence III- medium
    lintcode614- Binary Tree Longest Consecutive Sequence II- medium
    gstreamer在Ubuntu下构建开发环境 分类: ffmpeg-SDL-VLC-Live555 2015-04-07 17:56 324人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/terribleterrible/p/9912207.html
Copyright © 2011-2022 走看看