题意:
给你一个串数字,可以按任意顺序排列,求有几种排列可以使他们组成的数字可以被11整除。
思路:
和前几天那个被9整除的思想类似,1%11=1,10%11=10,100%11=1,1000%11=10.....容易观察出,设奇数位的和为x,偶数位的和为y,则(x+10y)%11的值为0就可以了--> (x-y+11y)%11=0 --> (x-y)%11=0。
然后就可以dp做了dp[i][j][k]分别表示,当前在放数字i-1,之前已经放了j个数字,现在(x-y)%11的值为k。
代码:
1 #include2 #include 3 #include 4 using namespace std; 5 #define MOD 1000000007 6 typedef long long LL; 7 LL C[110][110],num[15]; 8 LL dp[11][101][11]; 9 10 char ch[110];11 void init(){12 C[0][0]=C[1][0]=C[1][1]=1;13 for(int i=2;i<=100;i++){14 for(int j=0;j<=i;j++){15 if(j==0) C[i][j] = 1;16 else C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;17 }18 }19 }20 21 LL cal(int len){22 memset(dp,0,sizeof(dp));23 dp[0][0][0]=1;24 int sum = 0; int need = (len+1)>>1;25 for(int i=1;i<=10;i++){26 for(int j=0;j<=sum && j<=need;j++){27 for(int k=0;k<=num[i-1] && (j+k)<=need;k++){28 int change = (2*k-num[i-1])*(i-1)%11;29 if(change<0) change+=11;30 for(int l=0;l<11;l++){31 int next = (change + l)%11;32 dp[i][j+k][next] = (dp[i][j+k][next] + dp[i-1][j][l] * C[need-j][k] %MOD* C[len-need-sum+j][num[i-1]-k] %MOD)%MOD;33 }34 }35 }36 sum+=num[i-1];37 }38 return dp[10][need][0];39 }40 41 void solve(){42 memset(num,0,sizeof(num));43 for(int i=0;ch[i];i++){44 num[ch[i]-'0']++;45 }46 int len=strlen(ch);47 LL ans = cal(len);48 if(num[0]){49 num[0]--;50 LL ans2 = cal(len-1);51 ans=((ans-ans2)%MOD+MOD)%MOD;52 }53 cout< <