标签:求和 ring sizeof 理解 方案 ems 代码 can inf
1.zoj-4026
首先我们需要推倒一下,每次都是从A开始拿,可以列举几种情况,会发现最后结束一定是在第四次抽到A的时候结束的,因为假设在第二堆结束,你在抽完4次2后第二堆才为空,你需要第五次抽到2才会回到第二堆,这时候才能结束,不符合题意,因此只有第一次就被抽的A能结束游戏,因此结束的时候一定为A,因此A被抽完的可能性为ans【1】=1;
假设每种牌剩余数量分别为n1,...,n12n1,...,n12,对于2≤i≤122≤i≤12,如果ni=0ni=0说明四张ii都被拿走了,即ans[i]=1ans[i]=1,否则说明还有ii没有被拿走,此时若n1=0n1=0说明游戏已经结束,那么没有机会再拿走剩下的ii了,即ans[i]=0ans[i]=0,否则说明还有机会拿走全部的ii,此时问题转化为,m=48?nm=48?n张牌随意排列,要求在拿走第n1张AA之前拿走ni张ii,枚举最后一张A的位置j,用组合公式算出总方案数和满足条件的方案数,代码如下:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; typedef pair<int, int>P; const int INF = 0x3f3f3f3f, maxn = 15; int T, n, num[maxn]; ll C(int n, int m) { if (m<0 || m>n)return 0; ll ans = 1; for (int i = 1; i <= m; i++)ans = ans * (n - m + i) / i; return ans; } int V(char *s) { if (s[1])return 10; if (s[0] == ‘A‘)return 1; if (s[0] == ‘J‘)return 11; if (s[0] == ‘Q‘)return 12; return s[0] - ‘0‘; } ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; } int main() { scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= 12; i++)num[i] = 4; /*每张牌有4张*/ for (int i = 1; i <= n; i++) { char s[3]; scanf("%s", s); num[V(s)]--;/*每次被抽一次就减少一张*/ } n = 48 - n;/*剩下多少张牌没有被抽*/ printf("1");/*A被抽完的可能性为1*/ for (int i = 2; i <= 12; i++) if (!num[i])printf(" 1");/*若已被抽完则为1*/ else if (!num[1])printf(" 0");/*若A已被抽完且第i张牌没有被抽完就已没机会被抽完*/ else { ll q = C(n, num[1])*C(n - num[1], num[i]);/*总的方案数*/ ll p = 0; for (int j = num[1] + num[i]; j <= n; j++)p += C(j - 1, num[1] - 1)*C(j - num[1], num[i]);/*满足条件的方案数*/ ll g = gcd(p, q); p /= g, q /= g; if (p == 0)printf(" 0"); else if (p == q)printf(" 1"); printf(" %lld/%lld", p, q); } printf("\n"); } return 0; }
2.zoj-4027
假设现有n个括号,其中有两个左括号A和B,则最后移动完后A一定在B的左边,这是很关键的一点;
可知左括号与n个右括号交换,则得到的值是此左括号对应的值与被交换的右括号的值的总和;
dp数组的i行表示的是第i个左括号,因此这一行用来维护此左括号能得到的最大值,再与dp[i+1][j+1]相加,即可得到这两个左括号能得到的最大值的总和,建议画出dp图理解,代码如下:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; const int maxn = 1005; int T, n, nl, nr, val[maxn], num[maxn], sum[maxn], pos[maxn]; long long dp[maxn][maxn]; char s[maxn]; int main() { scanf("%d", &T); while (T--) { memset(s, ‘\0‘, sizeof(val)); memset(val, 0, sizeof(val)); memset(pos, 0, sizeof(pos)); memset(num, 0, sizeof(num)); memset(sum, 0, sizeof(sum)); memset(dp, 0, sizeof(dp)); scanf("%d", &n); scanf("%s", s + 1); for (int i = 1; i <= n; i++) scanf("%d", &val[i]); nl = nr = 0;/*nl用来记录左括号的总数,nr用来记录右括号的总数*/ for (int i = 1; i <= n; i++) if (s[i] == ‘(‘) { pos[++nl] = i;/*当出现左括号的时候,用pos数组来记录此括号的位置*/ num[nl] = nr;/*用num数组来记录此括号的左边的右括号的总数*/ } else { nr++; sum[nr] = sum[nr - 1] + val[i];/*用sum数组记录右括号的叠加和*/ } for (int i = nl; i >= 1; i--) { for (int j = n - (nl - i); j >= pos[i]; j--) { long long temp = (long long)val[pos[i]] * (sum[num[i] + j - pos[i]] - sum[num[i]]); dp[i][j] = dp[i + 1][j + 1] + temp; if (j<n - (nl - i))dp[i][j] = max(dp[i][j], dp[i][j + 1]); } for (int j = pos[i] - 1; j >= pos[i - 1]; j--) dp[i][j] = dp[i][j + 1]; } long long ans = 0; for (int j = 1; j <= n; j++) ans = max(ans, dp[1][j]); printf("%lld\n", ans); } return 0; }
3.zoj-4033
当 0<=i<n/2 时,将标记为0的男生分到3组,女生分到1组;
当 i >= n/2 时,将标记为1的男生分到3组,女生分到一组;
分别对1、3组和2、4组的权值求和,若不相等输出-1,否则输出位置。
#include <cstdio> #include <algorithm> #include <functional> #include <cstring> #include <iostream> #include <cmath> using namespace std; const int maxn=1e6+10,inf=(1<<30),mod=1e9+7; char que[maxn]; int place[maxn]; int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); scanf("%s",que); int sum1=0,sum2=0; for (int i=0;i<n/2;i++){ if(i%2==0) place[i]=0,sum1+=i+1; else place[i]=1,sum2+=i+1; } for (int i=n/2;i<n;i++){ if(i%2==0) place[i]=1,sum2+=i+1; else place[i]=0,sum1+=i+1; } if(sum1!=sum2){ printf("-1\n"); continue; } for (int i=0;i<n;i++){ if(que[i]==‘1‘){ if(place[i]) printf("4"); else printf("3"); } else { if(place[i]) printf("2"); else printf("1"); } } printf("\n"); } return 0; }
标签:求和 ring sizeof 理解 方案 ems 代码 can inf
原文地址:https://www.cnblogs.com/KasenBob/p/9991664.html