终于过了肝了一天啊,怎么我最近都在做细节码农题啊
(这种水平NOIP凉凉??)
luacs大家都可以想到用吧,一开始我的思路是把所有在p以内的%p==0的组合数预处理出来,那C(n/p,m/p)任取,但是好像有重算
仔细思考,其实一个组合数可以拆分成很多个C(x%p,y%p) x<y就有是k的倍数,把这个东西看成p进制,得到推论C(i,j)不是p的倍数当且仅当k进制下i的每一位分别大于等于j
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; int alen,a[110],blen,b[110]; LL S(LL x){return x%=mod,x*(x+1)/2%mod;} LL cal(LL a,LL b) { if(a<b)b=a; return (S(a)-S(a-b))%mod; } LL f[110][2][2];//第i个位,是否在n的上界边缘,是否在m的上界边缘,每一位i都大于等于j的方案数 int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T,K; scanf("%d%d",&T,&K); while(T--) { LL n,m,k; scanf("%lld%lld",&n,&m);if(n<m)m=n; alen=0,k=n;while(k>0)a[++alen]=k%K,k/=K; blen=0,k=m;while(k>0)b[++blen]=k%K,k/=K; for(int i=blen+1;i<=alen;i++)b[i]=0; int len=alen; memset(f,0,sizeof(f)); for(int u=0;u<=a[len];u++) for(int v=0;v<=b[len];v++) { if(u>=v) { if(u==a[len]&&v==b[len])f[len][1][1]++; else if(u==a[len])f[len][1][0]++; else if(v==b[len])f[len][0][1]++; else f[len][0][0]++; } } int c; for(int i=len-1;i>=1;i--) { c=0; for(int u=0;u<K;u++) for(int v=0;v<K;v++) { if(u>=v) { if(u<a[i]) { if(v<b[i]) { c++; f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][0][1]+f[i+1][1][0]+f[i+1][1][1])%mod; } if(v==b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][1][0])%mod; f[i][0][1]=(f[i][0][1]+f[i+1][0][1]+f[i+1][1][1])%mod; } if(v>b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][1][0])%mod; } } if(u==a[i]) { if(v<b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][0][1])%mod; f[i][1][0]=(f[i][1][0]+f[i+1][1][0]+f[i+1][1][1])%mod; } if(v==b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod; f[i][0][1]=(f[i][0][1]+f[i+1][0][1])%mod; f[i][1][0]=(f[i][1][0]+f[i+1][1][0])%mod; f[i][1][1]=(f[i][1][1]+f[i+1][1][1])%mod; } if(v>b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod; f[i][1][0]=(f[i][1][0]+f[i+1][1][0])%mod; } } if(u>a[i]) { if(v<b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0]+f[i+1][0][1])%mod; } if(v==b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod; f[i][0][1]=(f[i][0][1]+f[i+1][0][1])%mod; } if(v>b[i]) { f[i][0][0]=(f[i][0][0]+f[i+1][0][0])%mod; } } } } } LL ans=cal(n+1,m+1); for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) ans=(ans-f[1][i][j])%mod; printf("%lld ",(ans+mod)%mod); } return 0; }