题目描述
As we all know,Claire_ and ykwd are famous ACMers in BUPT ACM Group.They always play games together.Nowadays they play such a game:at first,Claire_ writes down a number,and then she selects a special digit(from 0 to 9),she removes all the special digits,then she get a group of non-special digits.Claire_ can use the group of non-special digits and limitless special digit to create new numbers.She is interested in how many positive numbers she create are less than the former number.She asks ykwd to solve this problem as soon as possible,otherwise ykwd would stand on his knees on the keyboard.Be notice leading zeros are not allowed.
输入格式
At first line,there is a number
T
which is the number of cases;
For each case,there is a number
N
(
length ≤ 1000
) and a digit(from 0 to 9).
输出格式
For each case,you should print the answer in one line.Because the answer can be so large that you should print the answer mod 20130303.
输入样例
3
1020 0
1020 1
2110 1
输出样例
7
2
13
用例:
输入:777 7
输出:2
组合数学。
设special digit为x.
设原数字长度是 n;
则重组后的长度小于n的数肯定小于原数,这些数就是由 non-special digits 和 i(0<=i<=《special digit的个数》)个special digit组成;
可用排列组合算;假如求由 111333322222 的任意组合可组成数的个数,相当于3个A球,4个B球,5个C球放入12个盒子里,每个盒子放一个球。
答案为C(12,3)*C(9,4)*C(5,5); 求时注意一下没有前缀0;
还有就是所有的位数都用,长度为n,这时要保证组成的数小于原数,
设这个数为736890987,如果第一位取1--6(注意前缀0),后面的数是可以任意取的,用上面的方法算一下; 如果第一位为7,第二位只能取不超过3的数,第二位去0--2时,后面可任意取;第二位取3时,第三为只能取不超过6的数……,有点数位dp 不能超过上界的意思;然后一直加到末位。。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 1010
char ch[1010];
int p[1010];
int bit[10];
ll mod=20130303;
ll c[N][N];
int x;
ll C(ll n,ll k)
{
if(c[n][k]!=-1) return c[n][k];
if(k==1) return c[n][k]=n;
if(k==0) return c[n][k]=1;
if(n==k) return 1;
if(k > (n>>1)) return c[n][k]=C(n,n-k);
return c[n][k]=(C(n-1,k-1)+C(n-1,k))%mod;
}
ll calc(ll sum,ll n)
{
int i;
ll ans=1;
int ff=0;
for(i=0;i<10;i++)
{
if(i!=x && bit[i]==0) continue;
if(i==x && n==0) continue;
ff=1;
if(i!=x){
if(i==0){
sum--;
ans=(ans*C(sum,bit[i]))%mod;
sum-=bit[i];
sum++;
}
else{
ans=(ans*C(sum,bit[i]))%mod;
sum-=bit[i];
}
}
else{
if(i==0){
sum--;
ans=(ans*C(sum,n))%mod;
sum-=n;
sum++;
}
else{
ans=(ans*C(sum,n))%mod;
sum-=n;
}
}
}
if(ff==0) return 0;
return ans;
}
ll com(ll sum)
{
ll ans=1;
int i;
for(i=0;i<10;i++)
{
if(!bit[i]) continue;
ans=(ans*C(sum,bit[i]))%mod;
sum-=bit[i];
}
return ans;
}
int main()
{
int t,i,j,k;
cin>>t;
memset(c,-1,sizeof(c));
while(t--)
{
scanf("%s%d",ch,&x);
int len=strlen(ch);
memset(bit,0,sizeof(bit));
for(i=0;i<len;i++){
bit[ch[i]-'0']++;
p[i]=ch[i]-'0';
}
ll sum=0;
for(i=0;i<10;i++)
if(i!=x) sum+=bit[i];
ll ans=0;
for(i=0;i<bit[x];i++)
{
ans=(ans+calc(sum+i,i))%mod;
}
sum+=bit[x];
for(i=0;i<len;i++)
{
for(j=0;j<p[i];j++)
{
if(i==0 && j==0) continue;
if(!bit[j]) continue;
bit[j]--;
ans=(ans+com(sum-1-i))%mod;
bit[j]++;
}
bit[p[i]]--;
}
cout<<ans<<endl;
}
}