#include <iostream> #include <fstream> using namespace std; const long long p = 1000000007; bool czy_skaszalna(int * tab, int rozm){ if(rozm==0) return 1; if(rozm==1) return 0; for(int i=1; i<rozm; i++) if(tab[i]==tab[0] && czy_skaszalna(tab+i+1, rozm-i-1)) return 1; return 0; } long long W[3001][3001]; ///W[i][j] - ilosc skaszalnych lasow dlugosci i o j dolaczeniach long long wydajny_rozw(int n, long long m){ if (n==1) return 0; long long zmpom; for(int i=0; i<3001; i++) for(int j=0; j<3001; j++) W[i][j]=0; for(int i=1; i<3001; i++) W[i][0]=0; for(int i=1; i<3001; i++) W[1][i]=0; for(int i=1; i<3001; i++) W[2][i]=0; W[1][1]=m; W[2][1]=(m*m) % p; for(int i=3; i<3001; i++) for(int j = 1; j<3001; j++) { W[i][j]=m*W[i-1][j]; W[i][j]%=p; zmpom = (j*(m-j)) % p; zmpom*=W[i-2][j]; zmpom %=p; W[i][j]+=p-zmpom; W[i][j]%=p; zmpom = ((j-1)*(m-j+1))%p; zmpom*=W[i-2][j-1]; zmpom %= p; W[i][j]+=zmpom; W[i][j]%=p; } long long zwrot=0; for(int j=1; j<3001; j++){ zwrot+=j*W[n-1][j]; zwrot %= p; } /* for(int j=0; j<=10; j++) printf("%d\t", j); for(int i=1; i<=10; i++){ printf("\n%d:\t", i); for(int j=1; j<=10; j++) printf("%lld\t", W[i][j]); } printf("\n"); */ return zwrot; } long long rozw_na_pale(int n, long long m){ int tab[n]; for(int i=0; i<n; i++) tab[i]=0; long long zwrot = 0; int j; while(true){ if(czy_skaszalna(tab, n)) zwrot++; tab[0]++; j=0; while(tab[j] == m){ if(j==n-1) return zwrot; tab[j]=0; j++; tab[j]++; } } } long long pot(int a, int b){ if(b==0) return 1; return a*pot(a, b-1); } int main() { int n; long long m; scanf("%d %lld", &n, &m); printf("%lld", wydajny_rozw(n, m)); //printf("\n%lld", rozw_na_pale(n, m)); return 0; //srand(time(NULL)); /* int tab[4]; for(int i=0; i<16; i++) { for(int j=0; j<4; j++) if(i & (1<<j)) tab[j]=2; else tab[j]=1; if(czy_skaszalna(tab, 4)){ for(int j=0; j<4; j++) cout << tab[j] << " "; cout << endl; } }*/ /* long long ans1, ans2; for(int i=1; i<=10; i++) for(int j=1; j<=10; j++) { //ans1 = rozw_na_pale(i, j); ans2= wydajny_rozw(i, j); printf("%d\t%d\t%d\t%lld\t%lld\n", i, j, (int) (ans1==ans2), ans1, ans2); } return 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 | #include <iostream> #include <fstream> using namespace std; const long long p = 1000000007; bool czy_skaszalna(int * tab, int rozm){ if(rozm==0) return 1; if(rozm==1) return 0; for(int i=1; i<rozm; i++) if(tab[i]==tab[0] && czy_skaszalna(tab+i+1, rozm-i-1)) return 1; return 0; } long long W[3001][3001]; ///W[i][j] - ilosc skaszalnych lasow dlugosci i o j dolaczeniach long long wydajny_rozw(int n, long long m){ if (n==1) return 0; long long zmpom; for(int i=0; i<3001; i++) for(int j=0; j<3001; j++) W[i][j]=0; for(int i=1; i<3001; i++) W[i][0]=0; for(int i=1; i<3001; i++) W[1][i]=0; for(int i=1; i<3001; i++) W[2][i]=0; W[1][1]=m; W[2][1]=(m*m) % p; for(int i=3; i<3001; i++) for(int j = 1; j<3001; j++) { W[i][j]=m*W[i-1][j]; W[i][j]%=p; zmpom = (j*(m-j)) % p; zmpom*=W[i-2][j]; zmpom %=p; W[i][j]+=p-zmpom; W[i][j]%=p; zmpom = ((j-1)*(m-j+1))%p; zmpom*=W[i-2][j-1]; zmpom %= p; W[i][j]+=zmpom; W[i][j]%=p; } long long zwrot=0; for(int j=1; j<3001; j++){ zwrot+=j*W[n-1][j]; zwrot %= p; } /* for(int j=0; j<=10; j++) printf("%d\t", j); for(int i=1; i<=10; i++){ printf("\n%d:\t", i); for(int j=1; j<=10; j++) printf("%lld\t", W[i][j]); } printf("\n"); */ return zwrot; } long long rozw_na_pale(int n, long long m){ int tab[n]; for(int i=0; i<n; i++) tab[i]=0; long long zwrot = 0; int j; while(true){ if(czy_skaszalna(tab, n)) zwrot++; tab[0]++; j=0; while(tab[j] == m){ if(j==n-1) return zwrot; tab[j]=0; j++; tab[j]++; } } } long long pot(int a, int b){ if(b==0) return 1; return a*pot(a, b-1); } int main() { int n; long long m; scanf("%d %lld", &n, &m); printf("%lld", wydajny_rozw(n, m)); //printf("\n%lld", rozw_na_pale(n, m)); return 0; //srand(time(NULL)); /* int tab[4]; for(int i=0; i<16; i++) { for(int j=0; j<4; j++) if(i & (1<<j)) tab[j]=2; else tab[j]=1; if(czy_skaszalna(tab, 4)){ for(int j=0; j<4; j++) cout << tab[j] << " "; cout << endl; } }*/ /* long long ans1, ans2; for(int i=1; i<=10; i++) for(int j=1; j<=10; j++) { //ans1 = rozw_na_pale(i, j); ans2= wydajny_rozw(i, j); printf("%d\t%d\t%d\t%lld\t%lld\n", i, j, (int) (ans1==ans2), ans1, ans2); } return 0; */ } |