Codeforces Gym 100342D Problem D. Dinner Problem Dp+高精度
题意:有n天,有k个人,安排这k个人做饭,问你有多少种安排方案,每个人至少得做一天饭
思路: dp[i][j] 表示 从k个人中选i个人做j天的饭有多少方案, dfs(i,j) 表示前i个人做j天的饭有多少方案
转移:
if(i == 0) dp[i][j]=dfs(i,j-1)*k; // 只能选“后面”k个
dp[i][j] = dfs(i-1,j-1)*i + dfs(i,j-1)*(k-i); // 从前i个中选一个人在第j天做饭或者从i+1到k个人里选一个。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef unsigned long long ll; 4 #define mem(a) memset(a,0,sizeof(a)) 5 #define mp(x,y) make_pair(x,y) 6 const int maxn = 410; 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 17 struct bign 18 { 19 int len, s[maxn]; 20 bign () 21 { 22 memset(s, 0, sizeof(s)); 23 len = 1; 24 } 25 bign (int num) { *this = num; } 26 bign (const char *num) { *this = num; } 27 bign operator = (const int num) 28 { 29 char s[maxn]; 30 sprintf(s, "%d", num); 31 *this = s; 32 return *this; 33 } 34 bign operator = (const char *num) 35 { 36 for(int i = 0; num[i] == '0'; num++) ; //去前导0 37 len = strlen(num); 38 for(int i = 0; i < len; i++) s[i] = num[len-i-1] - '0'; 39 return *this; 40 } 41 bign operator + (const bign &b) const //+ 42 { 43 bign c; 44 c.len = 0; 45 for(int i = 0, g = 0; g || i < max(len, b.len); i++) 46 { 47 int x = g; 48 if(i < len) x += s[i]; 49 if(i < b.len) x += b.s[i]; 50 c.s[c.len++] = x % 10; 51 g = x / 10; 52 } 53 return c; 54 } 55 bign operator += (const bign &b) 56 { 57 *this = *this + b; 58 return *this; 59 } 60 void clean() 61 { 62 while(len > 1 && !s[len-1]) len--; 63 } 64 bign operator * (const bign &b) //* 65 { 66 bign c; 67 c.len = len + b.len; 68 for(int i = 0; i < len; i++) 69 { 70 for(int j = 0; j < b.len; j++) 71 { 72 c.s[i+j] += s[i] * b.s[j]; 73 } 74 } 75 for(int i = 0; i < c.len; i++) 76 { 77 c.s[i+1] += c.s[i]/10; 78 c.s[i] %= 10; 79 } 80 c.clean(); 81 return c; 82 } 83 bign operator *= (const bign &b) 84 { 85 *this = *this * b; 86 return *this; 87 } 88 bign operator - (const bign &b) 89 { 90 bign c; 91 c.len = 0; 92 for(int i = 0, g = 0; i < len; i++) 93 { 94 int x = s[i] - g; 95 if(i < b.len) x -= b.s[i]; 96 if(x >= 0) g = 0; 97 else 98 { 99 g = 1; 100 x += 10; 101 } 102 c.s[c.len++] = x; 103 } 104 c.clean(); 105 return c; 106 } 107 bign operator -= (const bign &b) 108 { 109 *this = *this - b; 110 return *this; 111 } 112 bign operator / (const bign &b) 113 { 114 bign c, f = 0; 115 for(int i = len-1; i >= 0; i--) 116 { 117 f = f*10; 118 f.s[0] = s[i]; 119 while(f >= b) 120 { 121 f -= b; 122 c.s[i]++; 123 } 124 } 125 c.len = len; 126 c.clean(); 127 return c; 128 } 129 bign operator /= (const bign &b) 130 { 131 *this = *this / b; 132 return *this; 133 } 134 bign operator % (const bign &b) 135 { 136 bign r = *this / b; 137 r = *this - r*b; 138 return r; 139 } 140 bign operator %= (const bign &b) 141 { 142 *this = *this % b; 143 return *this; 144 } 145 bool operator < (const bign &b) 146 { 147 if(len != b.len) return len < b.len; 148 for(int i = len-1; i >= 0; i--) 149 { 150 if(s[i] != b.s[i]) return s[i] < b.s[i]; 151 } 152 return false; 153 } 154 bool operator > (const bign &b) 155 { 156 if(len != b.len) return len > b.len; 157 for(int i = len-1; i >= 0; i--) 158 { 159 if(s[i] != b.s[i]) return s[i] > b.s[i]; 160 } 161 return false; 162 } 163 bool operator == (const bign &b) 164 { 165 return !(*this > b) && !(*this < b); 166 } 167 bool operator != (const bign &b) 168 { 169 return !(*this == b); 170 } 171 bool operator <= (const bign &b) 172 { 173 return *this < b || *this == b; 174 } 175 bool operator >= (const bign &b) 176 { 177 return *this > b || *this == b; 178 } 179 string str() const 180 { 181 string res = ""; 182 for(int i = 0; i < len; i++) res = char(s[i]+'0') + res; 183 return res; 184 } 185 }; 186 187 istream& operator >> (istream &in, bign &x) 188 { 189 string s; 190 in >> s; 191 x = s.c_str(); 192 return in; 193 } 194 195 ostream& operator << (ostream &out, const bign &x) 196 { 197 out << x.str(); 198 return out; 199 } 200 201 202 bign dp[105][105]; 203 int k, n; 204 205 bign dfs(int i,int j){ 206 if(dp[i][j]!=-1) return dp[i][j]; 207 if(i > j) return dp[i][j]=0; 208 if(i==0 && j==0) return dp[i][j]=1; 209 if(i == 0) return dp[i][j]=dfs(i,j-1)*k; 210 return dp[i][j] = dfs(i-1,j-1)*i + dfs(i,j-1)*(k-i); // 从前i个中选一个人在第j天做饭或者从i+1到k个人里选一个。 211 } 212 213 int main(){ 214 freopen("dinner.in","r",stdin); 215 freopen("dinner.out","w",stdout); 216 //k=read(),n=read(); 217 cin >> k >> n; 218 // memset(dp,-1,sizeof(dp)); 219 for(int i = 0 ; i <= 100 ; ++ i) 220 for(int j = 0 ; j <= 100 ; ++ j) 221 dp[i][j] = -1; 222 cout << dfs(k,n) << endl; 223 224 return 0; 225 } 226 227 //http://codeforces.com/gym/100342/attachments