观察发现,对于0-9每个数字个数都确定的情况,比如样例的1个0,2个2,1个3,他们的总和是可以O(1)计算的:答案是 (num-1)*num/2 .
所以考虑枚举0-9每位是什么数字,然后进行计算.
具体地:先对12进行分解,即能用x+x+…表示出来,然后取小于10的部分,然后枚举数字的阶乘(也就是有这么多个x数字),最后算个组合数.
Flu实现的不是很精细,跑了5.467秒,不过已经足够.
在一个长度为n的数字里插m个0,不能有前导零,不许动原始数字,一共有这么多情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
| #include<bits/stdc++.h> #define i64 long long #define i128 __int128 using namespace std; template<typename T1,typename T2,typename T3> T1 qp(T1 b,T2 po,T3 p){ T1 res(1); while(po>0){ if(po&1) res=res*b%p; b=b*b%p; po>>=1; } return res; } long long yh[114][114]; void init(int num,long long mod=100000000000000003){ for(int i=1;i<=num;++i){ yh[i][1]=yh[i][i]=1; for(int j=2;j<i;++j){ yh[i][j]=(yh[i-1][j]+yh[i-1][j-1])%mod; } } } inline long long C(int n,int m){ return yh[n+1][m+1]; }
unordered_map<i64,i64>mp; i128 res=0;
int arr[100]; int hum[100]; int vis[100]; int lim=12;
i128 hhash(int num){ i128 rres=0; for(int i=0;i<=9;++i){ for(int j=1;j<=num;++j){ if(hum[j]==i){ rres+=arr[j]; break; } } rres*=19; } return rres; }
i128 calc(i128 num){ return (0+num-1)*(num)/2; } void chk2(int num){ int cnt=0,cnt0=0; for(int i=1;i<=num;++i){ if(hum[i]==0){ cnt0=arr[i]; }else{ cnt+=arr[i]; } } i128 rres=1; if(cnt0!=0){ rres=C(cnt+cnt0-1,cnt-1); } for(int i=1;i<=num;++i){ if(hum[i]==0){ }else{ rres*=C(cnt,arr[i]); cnt-=arr[i]; } } auto &pos=mp[hhash(num)]; rres=calc(rres); if(pos==0)pos=rres; else{ assert(pos==rres); } } void dfs2(int num,int tar){ if(num>tar){ chk2(tar); return; } for(int i=0;i<=9;++i){ if(vis[i]==0){ vis[i]=1; hum[num]=i; dfs2(num+1,tar); vis[i]=0; } } } void chk(int num){ if(num>10)return; dfs2(1,num); } void dfs(int num,int res,int pre){ if(res<=0){ chk(num-1); return; } for(int i=1;i<=min(pre,res);++i){ arr[num]=i; dfs(num+1,res-i,i); } arr[num]=0; }
int main(){ lim=12; init(100); dfs(1,lim,lim); for(auto i:mp){ res+=i.second; } cout<<(i64)res; return 0; }
|