早上随便搞搞t1t3就开始划水了,t2一看就是组合数学看着肚子疼...结果t1t3都a了??感天动地。
从小到大排序,从前到后枚举i,表示i是整个背包中不选的物品中代价最小的那个,即i不选,1到i-1全部都要选,i+1到n做背包(此时容量为m-pre),极限复杂度$O(n^3)$,可是我们在中间判断一下,当剩余容量比当前i代价小,break。可以减掉很大的复杂度!(cena评测最慢0.04s~
或者可以在枚举i时倒着枚举,每次背包就可以$O(n)$解决了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 #define RG register 7 8 using namespace std; 9 10 const int mod = 1000000007; 11 12 int n, m, a[1005]; 13 int f[1005]; 14 15 int main ( ) { 16 freopen ( "gift.in", "r", stdin ); 17 freopen ( "gift.out", "w", stdout ); 18 scanf ( "%d%d", &n, &m ); 19 for ( int i = 1; i <= n; i ++ ) { 20 scanf ( "%d", &a[i] ); 21 } 22 sort ( a + 1, a + 1 + n ); 23 ll ans = 0; int sum = 0; 24 for ( RG int i = 1; i <= n; i ++ ) { 25 memset ( f, 0, sizeof ( f ) ); 26 f[0] = 1; 27 for ( RG int k = i + 1; k <= n; k ++ ) { 28 if ( m - sum < a[k] ) break; 29 for ( RG int j = m - sum; j >= a[k]; j -- ) { 30 f[j] = ( f[j] + f[j-a[k]] ) % mod; 31 } 32 } 33 for ( RG int j = max ( m - sum - a[i] + 1, 0 ); j <= m - sum; j ++ ) 34 ans = ( ans + f[j] ) % mod; 35 sum += a[i]; 36 } 37 printf ( "%d", ans ); 38 return 0; 39 }
题意是要求该序列-1的累加和永远小于等于1的累加和的概率。经典的卡特兰数问题,在坐标系中,可以把-1看成向上走,把1看成向右走,最终目标是计算从原点走到$(n,m)$并且过程中不能超出到$y=x$这条直线的方案数。方案数为$C_{m+n}^m-C_{m+n}^{m-1}$,即$\frac{n-m+1}{n+1}$
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 int main ( ) { 6 freopen ( "fseq.in", "r", stdin ); 7 freopen ( "fseq.out", "w", stdout ); 8 int T; 9 scanf ( "%d", &T ); 10 while ( T -- ) { 11 int n, m; 12 scanf ( "%d%d", &n, &m ); 13 if ( n < m ) printf ( "0.000000\n" ); 14 else printf ( "%.6lf", ( double ) ( n - m + 1 ) / ( double ) ( n + 1 ) ); 15 } 16 return 0; 17 }
感觉我的方法是碰巧遇到可以过的类型了...如果题目不合法的对应关系改一下马上就会挂。
但是题目给的是对应不能相同嘛~我定义的$dp[dep][up][tot]$分别表示当前数的位置,是否顶上界,已经填了多少个数(抛开前导零,记忆化的时候会发现,除了顶上界的情况只会计算一次并且不会第二次返回,不顶上界的情况计算一次后每次都直接返回了,不管前面填的什么数和后面将填什么数...
可是对于这道题它恰好就是对的!在不顶上界的情况,所有数字都可以填,并且所有数字都有相同的不合法情况个数!所以直接记忆化就没有问题...
可是$yuli$dalao(%%%指出,只要把题稍微改一改,比如对应位置不能同时为质数之类的...每个数的方案数就不一样了!
所以正解是枚举数的长度,从前后同时填数即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 7 ll dp[20][2][20]; 8 int num[20], fi[20]; 9 10 ll dfs ( int dep, int up, int tot ) { 11 if ( dp[dep][up][tot] ) return dp[dep][up][tot]; 12 if ( !dep && tot ) return 1; 13 if ( !dep ) return 0; 14 int MA = up ? num[dep] : 9; 15 ll res = 0; 16 for ( int i = 0; i <= MA; i ++ ) { 17 if ( i == 0 && !tot ) res += dfs ( dep - 1, up && i == MA,tot ); 18 else if ( fi[tot + 1] != i ) { 19 fi[dep] = i; 20 res += dfs ( dep - 1, up && i == MA, tot + 1 ); 21 fi[dep] = -1; 22 } 23 } 24 dp[dep][up][tot] = res; 25 return res; 26 } 27 28 ll work ( ll x ) { 29 int cnt = 0; 30 memset ( fi, -1, sizeof ( fi ) ); 31 memset ( dp, 0, sizeof ( dp ) ); 32 while ( x ) { 33 num[++cnt] = x % 10; 34 x /= 10; 35 } 36 return dfs ( cnt, 1, 0 ); 37 } 38 39 int main ( ) { 40 freopen ( "lucky.in", "r", stdin ); 41 freopen ( "lucky.out", "w", stdout ); 42 ll x, y; 43 scanf ( "%I64d%I64d", &x, &y ); 44 ll xx = work ( x - 1 ), yy = work ( y ); 45 printf ( "%I64d", yy - xx ); 46 }
// wans
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 ll l,r,dp[12][2][2]; 6 int tot,dig[30]; 7 bool vis[12][2][2]; 8 9 ll dfs(int dep,bool lf_up,bool rg_up) { 10 11 if(vis[dep][lf_up][rg_up]) return dp[dep][lf_up][rg_up]; 12 if(dep == tot - dep + 1) { 13 if(lf_up && rg_up) return dig[dep]; 14 else if(! lf_up) return 10; 15 else if(lf_up) return dig[dep] + 1; 16 } 17 if(dep > tot - dep + 1) { 18 if(lf_up && rg_up) return 0; 19 return 1; 20 } 21 vis[dep][lf_up][rg_up] = true; 22 int up = lf_up ? dig[tot - dep + 1] : 9; 23 ll res = 0; 24 for(int i = 0;i <= up;i ++) 25 for(int j = 0;j <= 9;j ++) { 26 if(i == j) continue; 27 if(dep == 1 && i == 0) continue; 28 bool upup; 29 if(j > dig[dep]) upup = true; 30 else if(j < dig[dep]) upup = false; 31 else upup = rg_up; 32 res += dfs(dep + 1,lf_up && (i == dig[tot - dep + 1]),upup); 33 } 34 return dp[dep][lf_up][rg_up] = res; 35 } 36 37 ll solve(ll s) { 38 39 memset(vis,0,sizeof(vis)); 40 ll ss = s,ans = 0; 41 tot = 0; 42 while(s) { 43 dig[++ tot] = s % 10; 44 s /= 10; 45 } 46 ans += dfs(1,1,0); 47 for(int i = 1;i <= tot;i ++) dig[i] = 9; 48 for(tot = tot - 1;tot >= 1;tot --) { 49 memset(vis,0,sizeof(vis)); 50 ans += dfs(1,1,0); 51 } 52 return ans; 53 } 54 55 int main( ) { 56 57 freopen("lucky.in","r",stdin); 58 freopen("lucky.out","w",stdout); 59 scanf("%I64d%I64d",& l,& r); 60 ll ans1 = solve(l - 1); 61 ll ans2 = solve(r); 62 printf("%I64d",ans2 - ans1); 63 }
//yuli