暑假第十九测
題解:第一題:為了不重復,我們只能算某一個物品被剩下時不能選的方案;
我們枚舉第幾小的物品不能選,則他前面都能選,所以我們需要的體積是sum[[i - 1] -- sum[i - 1] + v[i] - 1, 達到這個體積的方案數怎么求,我們可以先倒著做一遍dp; 那么我們就可以知道裝滿dp[m - sum[i - 1]] -- dp[m - sum[i] - v[i] + 1] 的方案數了;
對于第 i 小不選的方案數為 sum (dp[i + 1][m - sum[i - 1] ---- m - sum[i] - v[i] + 1] );
這個dp方程還是要好好想想的,可以從后面做一次來優化轉移的復雜度
#include<bits/stdc++.h> using namespace std; const int M = 1005, mod = 1000000007; int dp[M][M], ans, sum[M], n, m, v[M]; inline int moc(int a){return a >= mod ? a - mod : a;};int main(){freopen("gift.in","r",stdin);freopen("gift.out","w",stdout);scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++)scanf("%d", &v[i]);sort(v + 1, v + 1 + n);for(int i = 1; i <= n; i++)sum[i] = sum[i - 1] + v[i];dp[n + 1][0] = 1;for(int i = n; i >= 1; i--){for(int j = 0; j < v[i]; j++)dp[i][j] = dp[i + 1][j];for(int j = m; j >= v[i]; j--)dp[i][j] = moc(dp[i + 1][j] + dp[i + 1][j - v[i]]);}for(int i = 1; i <= n; i++){int res = m - sum[i - 1];for(int j = res; j >= max(0, res - v[i]); j--)ans = moc(ans + dp[i + 1][j]);}printf("%d\n", ans); } View Code?
第二題:
算法:組合數學題
可以將原問題轉化一下,看成是在一個二維平面上行走,+1看成移動(1,0)
-1看成移動(0,1),那么到達(N,M)點且路線又不走到y=x這條直線上方的路線總數就是
答案,這個組合問題很經典,方案數為C(M,M+N)-C(M-1,M+N),所以
可以知道答案就是1-M/(N+1)
我忘特判n < m了
#include<bits/stdc++.h> using namespace std; #define ll long longint main(){freopen("fseq.in","r",stdin);freopen("fseq.out","w",stdout);int T;scanf("%d", &T);while(T--){double n, m;scanf("%lf%lf", &n, &m);if(n < m)printf("0.000000\n");else printf("%.6lf\n", 1 - m/(n+1));} } View Code?
第三題:數位dp; 但是我們發現前面的數會對后面產生影響,當總位數為 7, 8時, 第一位上的限制是不一樣的,所以dp要限制一個總位數,開一個vis[總位數][dep]記錄dep位不能填什么,為什么這樣就沒有影響呢?
因為總位數一樣時,最高位填3或4,最低位都有9個數可以選擇,而中間的情況是一樣的;
#include<bits/stdc++.h> using namespace std; #define ll long long ll dp[20][20][2], vis[20][20]; int digit[20]; ll dfs(int tot, int dep, int f, int zero){if(!dep)return 1;if(dp[tot][dep][f] != -1)return dp[tot][dep][f];int i = f ? digit[dep] : 9;ll tmp = 0;for( ; i >= 0; i--){if(i != vis[tot][dep]){tot -= (zero & (i == 0));if(dep > (tot + 1)/2) vis[tot][tot - dep + 1] = i;tmp += dfs(tot, dep - 1, f & (i == digit[dep]), zero & (i == 0)); }}return dp[tot][dep][f] = tmp; }ll get(ll x){memset(dp ,-1, sizeof(dp));memset(vis, -1, sizeof(vis));int cnt = 0;while(x){digit[++cnt] = x%10;x /= 10;}return dfs(cnt, cnt, 1, 1); } int main(){freopen("lucky.in","r",stdin);freopen("lucky.out","w",stdout);ll L, R;cin>>L>>R;ll ans1 = get(R);ll ans2 = get(L-1);//cout<<ans2<<" "<<ans1<<endl;cout<<ans1-ans2<<endl; } View Code?
?
今天爆零了!!!!!
轉載于:https://www.cnblogs.com/EdSheeran/p/9502096.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: android 录屏
- 下一篇: NTA告警引发的dll劫持思考(溯源)