• UOJ#275. 【清华集训2016】组合数问题 数位dp


    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ275.html

    题解

    用卢卡斯定理转化成一个 k 进制意义下的数位 dp 即可。

    算答案的时候补集转化一下会好写一些。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    LL read(){
    	LL x=0,f=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		f|=ch=='-',ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    const int N=105,mod=1e9+7;
    int T,k;
    LL n,m;
    int C[N][N];
    int dp[64+5][2][2][2];
    int vn[N],vm[N],cn,cm;
    int calc(LL n,LL m){
    	int a=(n+1)%mod,b=(n-m)%mod;
    	a=1LL*a*(a+1)/2%mod;
    	b=1LL*b*(b+1)/2%mod;
    	a=(a-b+mod)%mod;
    	return a;
    }
    void Add(int &x,int y){
    	if ((x+=y)>=mod)
    		x-=mod;
    }
    int DP(int d,int fe,int fn,int fm){
    	if (!d)
    		return 1;
    	int &ans=dp[d][fe][fn][fm];
    	if (~ans)
    		return ans;
    	ans=0;
    	int ln=fn?vn[d]:k-1;
    	int lm=fm?vm[d]:k-1;
    	for (int i=0;i<=ln;i++)
    		for (int j=fe?min(i,lm):lm;j>=0;j--)
    			if (C[i][j])
    				Add(ans,DP(d-1,fe&&i==j,fn&&i==vn[d],fm&&j==vm[d]));
    	return ans;
    }
    void solve(){
    	n=read(),m=read();
    	m=min(n,m);
    	int All=calc(n,m);
    	if (k==1)
    		return (void)(printf("%lld
    ",All));
    	cn=cm=0;
    	memset(vn,0,sizeof vn);
    	memset(vm,0,sizeof vm);
    	while (n)
    		vn[++cn]=n%k,n/=k;
    	while (m)
    		vm[++cm]=m%k,m/=k;
    	memset(dp,-1,sizeof dp);
    	cout << (All-DP(cn,1,1,1)+mod)%mod << endl;
    }
    int main(){
    	T=read(),k=read();
    	for (int i=0;i<k;i++)
    		C[i][0]=C[i][i]=1%k;
    	for (int i=1;i<k;i++)
    		for (int j=1;j<k;j++)
    			C[i][j]=(C[i-1][j-1]+C[i-1][j])%k;
    	while (T--)
    		solve();
    	return 0;
    }
    

      

  • 相关阅读:
    C/C++中volatile关键字详解(转)
    Spring中 @Autowired标签与 @Resource标签 的区别(转)
    [转]各种互斥量的总结
    nginx限制ip访问(转)
    HDU 4833 Best Financing (DP)
    HDU 4832 Chess (DP)
    HDU 4831 Scenic Popularity
    POJ 2155 Matrix (二维线段树)
    POJ 2155 Matrix (二维树状数组)
    HDU 4819 Mosaic (二维线段树)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ275.html
Copyright © 2020-2023  润新知