#pragma GCC optimize("Ofast") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("inline") #include using namespace std; #define MD (1000000007U) struct Modint{ unsigned val; Modint(){ val=0; } Modint(int a){ val = ord(a); } Modint(unsigned a){ val = ord(a); } Modint(long long a){ val = ord(a); } Modint(unsigned long long a){ val = ord(a); } inline unsigned ord(unsigned a){ return a%MD; } inline unsigned ord(int a){ a %= (int)MD; if(a < 0){ a += MD; } return a; } inline unsigned ord(unsigned long long a){ return a%MD; } inline unsigned ord(long long a){ a %= (int)MD; if(a < 0){ a += MD; } return a; } inline unsigned get(){ return val; } inline Modint &operator++(){ val++; if(val >= MD){ val -= MD; } return *this; } inline Modint &operator--(){ if(val == 0){ val = MD - 1; } else{ --val; } return *this; } inline Modint operator++(int a){ Modint res(*this); val++; if(val >= MD){ val -= MD; } return res; } inline Modint operator--(int a){ Modint res(*this); if(val == 0){ val = MD - 1; } else{ --val; } return res; } inline Modint &operator+=(Modint a){ val += a.val; if(val >= MD){ val -= MD; } return *this; } inline Modint &operator-=(Modint a){ if(val < a.val){ val = val + MD - a.val; } else{ val -= a.val; } return *this; } inline Modint &operator*=(Modint a){ val = ((unsigned long long)val*a.val)%MD; return *this; } inline Modint &operator/=(Modint a){ return *this *= a.inverse(); } inline Modint operator+(Modint a){ return Modint(*this)+=a; } inline Modint operator-(Modint a){ return Modint(*this)-=a; } inline Modint operator*(Modint a){ return Modint(*this)*=a; } inline Modint operator/(Modint a){ return Modint(*this)/=a; } inline Modint operator+(int a){ return Modint(*this)+=Modint(a); } inline Modint operator-(int a){ return Modint(*this)-=Modint(a); } inline Modint operator*(int a){ return Modint(*this)*=Modint(a); } inline Modint operator/(int a){ return Modint(*this)/=Modint(a); } inline Modint operator+(long long a){ return Modint(*this)+=Modint(a); } inline Modint operator-(long long a){ return Modint(*this)-=Modint(a); } inline Modint operator*(long long a){ return Modint(*this)*=Modint(a); } inline Modint operator/(long long a){ return Modint(*this)/=Modint(a); } inline Modint operator-(void){ Modint res; if(val){ res.val=MD-val; } else{ res.val=0; } return res; } inline operator bool(void){ return val!=0; } inline operator int(void){ return get(); } inline operator long long(void){ return get(); } inline Modint inverse(){ int a = val; int b = MD; int u = 1; int v = 0; int t; Modint res; while(b){ t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } if(u < 0){ u += MD; } res.val = u; return res; } inline Modint pw(unsigned long long b){ Modint a(*this); Modint res; res.val = 1; while(b){ if(b&1){ res *= a; } b >>= 1; a *= a; } return res; } inline bool operator==(int a){ return ord(a)==val; } inline bool operator!=(int a){ return ord(a)!=val; } } ; inline Modint operator+(int a, Modint b){ return Modint(a)+=b; } inline Modint operator-(int a, Modint b){ return Modint(a)-=b; } inline Modint operator*(int a, Modint b){ return Modint(a)*=b; } inline Modint operator/(int a, Modint b){ return Modint(a)/=b; } inline Modint operator+(long long a, Modint b){ return Modint(a)+=b; } inline Modint operator-(long long a, Modint b){ return Modint(a)-=b; } inline Modint operator*(long long a, Modint b){ return Modint(a)*=b; } inline Modint operator/(long long a, Modint b){ return Modint(a)/=b; } inline int my_getchar_unlocked(){ static char buf[1048576]; static int s = 1048576; static int e = 1048576; if(s == e && e == 1048576){ e = fread_unlocked(buf, 1, 1048576, stdin); s = 0; } if(s == e){ return EOF; } return buf[s++]; } struct MY_WRITER{ char buf[1048576]; int s; int e; MY_WRITER(){ s = 0; e = 1048576; } ~MY_WRITER(){ if(s){ fwrite_unlocked(buf, 1, s, stdout); } } } ; MY_WRITER MY_WRITER_VAR; void my_putchar_unlocked(int a){ if(MY_WRITER_VAR.s == MY_WRITER_VAR.e){ fwrite_unlocked(MY_WRITER_VAR.buf, 1, MY_WRITER_VAR.s, stdout); MY_WRITER_VAR.s = 0; } MY_WRITER_VAR.buf[MY_WRITER_VAR.s++] = a; } inline void wt_L(char a){ my_putchar_unlocked(a); } inline void wt_L(int x){ int s=0; int m=0; char f[10]; if(x<0){ m=1; x=-x; } while(x){ f[s++]=x%10; x/=10; } if(!s){ f[s++]=0; } if(m){ my_putchar_unlocked('-'); } while(s--){ my_putchar_unlocked(f[s]+'0'); } } inline void wt_L(Modint x){ int i; i = (int)x; wt_L(i); } long long cReader_ll(long long mn, long long mx, char nx){ int i; int fg = 0; int m = 1; int f = -1; long long res = 0; double tmp = 0; for(;;){ i = my_getchar_unlocked(); if(fg==0 && i=='-'){ fg++; m = -1; } else if('0' <= i && i <= '9'){ fg++; if(f == -1){ f = i - '0'; } res = 10 * res + i - '0'; tmp = 10 * tmp + i - '0'; assert(tmp < 1e20); } else{ break; } } assert(tmp / 2 <= res); assert((m==1 && fg >= 1) || (m==-1 && fg >= 2)); assert(mn <= m * res && m * res <= mx); assert(!(res == 0 && m == -1)); assert(!(res != 0 && f == 0)); assert(!(res == 0 && fg >= 2)); assert(i == nx); return m * res; } void cReader_eof(){ int i; i = my_getchar_unlocked(); assert(i == EOF); } int A; int B; int C; int N; Modint dp[51][51][51]; Modint p[51][151]; Modint tmp; Modint res[3]; int main(){ int cTE1_r3A, i; A = cReader_ll(1, 50, ' '); B = cReader_ll(1, 50, ' '); C = cReader_ll(1, 50, ' '); N = cReader_ll(1, 50, '\n'); cReader_eof(); for(i=(1);i<(51);i++){ int j; for(j=(3);j<(151);j++){ p[i][j] = ((Modint) i * (i-1)) / ((Modint) j * (j-1)); } } dp[A][B][C] = 1; for(cTE1_r3A=(0);cTE1_r3A<(N);cTE1_r3A++){ for(i=(1);i<(A+1);i++){ int j; for(j=(1);j<(B+1);j++){ int k; for(k=(1);k<(C+1);k++){ tmp = dp[i][j][k]; dp[i-1][j][k] += tmp * p[i][i+j+k]; dp[i][j-1][k] += tmp * p[j][i+j+k]; dp[i][j][k-1] += tmp * p[k][i+j+k]; dp[i][j][k] -= tmp * (p[i][i+j+k] + p[j][i+j+k] + p[k][i+j+k]); } } } } for(i=(1);i<(A+1);i++){ int j; for(j=(1);j<(B+1);j++){ int k; for(k=(1);k<(C+1);k++){ res[0] += (A-i) * dp[i][j][k]; res[1] += (B-j) * dp[i][j][k]; res[2] += (C-k) * dp[i][j][k]; } } } { int jbtyPBGc; if(3==0){ wt_L('\n'); } else{ for(jbtyPBGc=(0);jbtyPBGc<(3-1);jbtyPBGc++){ wt_L(res[jbtyPBGc]); wt_L(' '); } wt_L(res[jbtyPBGc]); wt_L('\n'); } } { Modint chk1; Modint chk2; string s1 = "3452192328044966520392806880021097467"; string s2 = "1921444247213913479420805120000000000"; string s3 = "1171514706712320746421671594290613233"; string s4 = "1097968141265093416811888640000000000"; string s5 = "5105000684786014790930854501796258921"; string s6 = "11528665483283480876524830720000000000"; chk1 = chk2 = 0; for(i=(0);i<(s1.size());i++){ chk1 = chk1 * 10 + s1[i] - '0'; } for(i=(0);i<(s2.size());i++){ chk2 = chk2 * 10 + s2[i] - '0'; } wt_L(chk1 / chk2); wt_L('\n'); chk1 = chk2 = 0; for(i=(0);i<(s3.size());i++){ chk1 = chk1 * 10 + s3[i] - '0'; } for(i=(0);i<(s4.size());i++){ chk2 = chk2 * 10 + s4[i] - '0'; } wt_L(chk1 / chk2); wt_L('\n'); chk1 = chk2 = 0; for(i=(0);i<(s5.size());i++){ chk1 = chk1 * 10 + s5[i] - '0'; } for(i=(0);i<(s6.size());i++){ chk2 = chk2 * 10 + s6[i] - '0'; } wt_L(chk1 / chk2); wt_L('\n'); } return 0; } // cLay version 20210819-1 [beta] // --- original code --- // int A, B, C, N; // Modint dp[51][51][51], p[51][151], tmp, res[3]; // { // A = cReader_ll(1, 50, ' '); // B = cReader_ll(1, 50, ' '); // C = cReader_ll(1, 50, ' '); // N = cReader_ll(1, 50, '\n'); // cReader_eof(); // rep(i,1,51) rep(j,3,151) p[i][j] = ((Modint) i * (i-1)) / ((Modint) j * (j-1)); // dp[A][B][C] = 1; // rep(N){ // rep(i,1,A+1) rep(j,1,B+1) rep(k,1,C+1){ // tmp = dp[i][j][k]; // dp[i-1][j][k] += tmp * p[i][i+j+k]; // dp[i][j-1][k] += tmp * p[j][i+j+k]; // dp[i][j][k-1] += tmp * p[k][i+j+k]; // dp[i][j][k] -= tmp * (p[i][i+j+k] + p[j][i+j+k] + p[k][i+j+k]); // } // } // rep(i,1,A+1) rep(j,1,B+1) rep(k,1,C+1){ // res[0] += (A-i) * dp[i][j][k]; // res[1] += (B-j) * dp[i][j][k]; // res[2] += (C-k) * dp[i][j][k]; // } // wt(res(3)); // // { // Modint chk1, chk2; // string s1 = "3452192328044966520392806880021097467"; // string s2 = "1921444247213913479420805120000000000"; // string s3 = "1171514706712320746421671594290613233"; // string s4 = "1097968141265093416811888640000000000"; // string s5 = "5105000684786014790930854501796258921"; // string s6 = "11528665483283480876524830720000000000"; // // chk1 = chk2 = 0; // rep(i,s1.size()) chk1 = chk1 * 10 + s1[i] - '0'; // rep(i,s2.size()) chk2 = chk2 * 10 + s2[i] - '0'; // wt(chk1 / chk2); // // chk1 = chk2 = 0; // rep(i,s3.size()) chk1 = chk1 * 10 + s3[i] - '0'; // rep(i,s4.size()) chk2 = chk2 * 10 + s4[i] - '0'; // wt(chk1 / chk2); // // chk1 = chk2 = 0; // rep(i,s5.size()) chk1 = chk1 * 10 + s5[i] - '0'; // rep(i,s6.size()) chk2 = chk2 * 10 + s6[i] - '0'; // wt(chk1 / chk2); // } // // }