• [SPOJ]SELTEAM


    原题链接

    题意

    大致意思:
    (n)个人中选取(k)个人组成一个球班,然后在这个球班里面任选人数组成球队,再在球队里面选取一名队长,求方案数。

    分析

    就一句话:给定(n,k)求下面式子的值(sum{(C_n^i imes (sum{(C_i^p imes p)}))})
    发现(T,n,k)都巨大,所以考虑每次查询的复杂度应该是(O(logn))
    阶乘预处理阶乘和阶乘逆元。
    这样子我们每次询问就是(O(n^2))了,总复杂度(O(TN^2))
    但是好像预处理出inv[3]==0。。。
    啥玩意啊????
    等等…
    模数好像不是质数。。。

    想了半天没有思路,然后只好跑去看题解。。。
    我们发现先选好球班和队长之后,其他人再考虑要不要加入球队。
    那么我们有一个新的计算方法(sum{(c_n^i*i*2^(i-1)),1le ile k})
    然后就是这道神仙题神仙的地方了。
    不看题解我一辈子都想不出来。
    玄机在模数上:(8388608=2^{23})
    所以(n-ige 23)的部分我们都不用算了。。。
    我们大力组合数只要开(10^5 imes 23)的辅助空间就可以艹过去了。。。。。

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <queue>
    #include <vector>
    #define ull unsigned long long
    #define ll long long
    using namespace std;
    const int ti=1e4+100,N=1e5;
    const int mod=8388608;
    ll read(){
    	char c;ll num,f=1;
    	while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
    	while(c=getchar(), isdigit(c))num=num*10+c-'0';
    	return f*num;
    }
    ll n,k,C[N+1000][30];
    ll ans,tmp;
    void init(){
    	for(int i=0;i<=N+100;i++){
    		C[i][0]=1;
    		for(int j=1;j<=min(23,i);j++)
    			C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
    	}
    }
    void add(ll &a,ll b){
    	a+=b;
    	if(a>=mod)a-=mod;
    }
    void work(){
    	n=read();k=read();ans=0;
    	for(int i=1;i<=min(k,23ll);i++)
    		add(ans,C[n][i]*i%mod*(1<<(i-1))%mod);
    	printf("%lld
    ",ans);
    }
    int main()
    {
    	init();
    	int Case=read();
    	while(Case--)work();
    	return 0;
    }
    
  • 相关阅读:
    js方法随机抽取n个随机数
    js里面函数的内部属性
    js中字符串支持正则表达式的方法
    扑克牌交换经典案例
    js里面进行位运算时候的注意事项
    js里面声明变量时候的注意事项
    三种方式加入媒体样式
    如何让多文本内容只显示一行,其余用省略号来显示
    background-clip和background-origin
    闲谈--心态 (zhuan)
  • 原文地址:https://www.cnblogs.com/onglublog/p/9913075.html
Copyright © 2020-2023  润新知