• P6669 组合数问题


    https://www.luogu.com.cn/problem/P6669
    数位dp+lucas定理

    给顶 (n,m,k),求 对于 (0le ile n,0le jle min(i,m)),有多少对 ((i,j)) 满足 ( binom{i}{j})(k) 的倍数

    其实要求的就是 ( binom{i}{j}mod k=0) 的个数
    由于 (k) 是小质数,所以可以根据 lucas 定理,转换为要求有多少 (i=(a_1 a_2cdots a_p)_kle n,j=(b_1 b_2cdots b_p)_kle min(i,m)),使得 (dbinom{a_1}{b_1}cdot dbinom{a_2}{b_2}cdots dbinom{a_p}{b_p}mod k=0)
    其中,((a_1 a_2cdots a_p)_k,(b_1 b_2cdots b_p)_k)(i,j)(k) 进制展开形式,(p) 取它们之间较大的位数
    那么上述式子 (mod k)(0),当且仅当存在一个 (u),使得 (a_u<b_u)

    然后就是做一个 (k) 进制下的数位dp,(f(pos,ok,ij,in,jm)) 表示当前是第 (pos) 位,满足条件的 (u) 是否已经出现过,后三位分别表示 (i,j)(i,n)(j,m) 之间顶不顶上界
    就可以记忆化搜索了

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN puts("")
    inline long long read(){
    	register long long x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=getchar();}
    	return y?x:-x;
    }
    #define mod 1000000007
    int k;
    long long n,m;
    long long f[68][2][2][2][2];
    int nn[68],mm[68];
    long long work(int pos,int ok,int ij,int in,int jm){
    	if(!pos) return ok;
    	long long &ret=f[pos][ok][ij][in][jm];
    	if(~ret) return ret;
    	ret=0;
    	int limi=in?nn[pos]:(k-1),limj=jm?mm[pos]:(k-1);
    	for(reg int i=0;i<=limi;i++)for(reg int j=0;j<=limj&&(j<=i||!ij);j++){
    		ret=(ret+work(pos-1,ok|(i<j),ij&(i==j),in&(i==limi),jm&(j==limj)))%mod;
    	}
    	return ret;
    }
    int main(){
    	int T=read();k=read();
    	while(T--){
    		n=read();m=read();
    		std::memset(nn,0,sizeof nn);std::memset(mm,0,sizeof mm);
    		nn[0]=mm[0]=0;
    		while(n) nn[++nn[0]]=n%k,n/=k;
    		while(m) mm[++mm[0]]=m%k,m/=k;
    		std::memset(f,-1,sizeof f);
    		printf("%lld
    ",work(std::max(nn[0],mm[0]),0,1,1,1));
    	}
    	return 0;
    }
    
  • 相关阅读:
    带有参数的存储过程
    不实用数据库实现保存和查询功能
    http错误代码(快速了解错误所在)
    ListBox的应用(左边中的信息移至右边)
    省市县三级连动(数据在一个表中)
    简单的实现用户注册时,向其油箱发送激活码邮件,并进行状态处理。 .
    省级三连动(二)
    省市选择期三级联动
    百钱百鸡
    MySQL命令简单应用
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/14056243.html
Copyright © 2020-2023  润新知