A:
题意:
有三个项目和n个学生,每个学生都擅长其中一个项目,现在要组成三个人的队伍,其中每个人恰好擅长其中一门,问能组成多少支队伍。
分析:
最多能组成的队伍的个数就是擅长项目里的最少学生。
1 #include2 #include 3 #include 4 5 using namespace std; 6 7 int main(void) 8 { 9 int n, x;10 vector a[4];11 scanf("%d", &n);12 for(int i = 1; i <= n; ++i)13 {14 scanf("%d", &x);15 a[x].push_back(i);16 }17 int aa = a[1].size(), bb = a[2].size(), cc = a[3].size();18 int ans = min(aa, bb);19 ans = min(ans, cc);20 printf("%d\n", ans);21 for(int i = 0; i < ans; ++i)22 printf("%d %d %d\n", a[1][i], a[2][i], a[3][i]);23 24 return 0;25 }
B:
题意:
有n个学生排成一队,他们有各自的学号(学号互不相同),现在知道每名学生前面那个人的学号ai和后面同学的学号bi,没有前驱或后继的补0,给出的顺序是任意的。要求顺序输出这些学号。
分析:
显然0是我们的突破点。如果n是偶数,从a中的那个0开始往后面推我们能得到排在偶数为的学号,从b中的0往前推,能得到奇数位置的学号。
n为奇数就略为棘手,不管从哪个0开始推,都只能得到偶数位置的学号。所以我们要另外分析奇数位置,发现:第一个学号是a、b中只出现一次且在a中的学号,找到这个头我们就可以往后面推了,当然如果找到的是b中只出现一次的那个尾也可以往前推。
代码比较挫,还是贴上来吧,毕竟是自己的孩子啊。
1 #include2 3 const int maxn = 1000000 + 10; 4 int left[maxn], right[maxn], cnt[maxn], vis[maxn]; 5 int ans[maxn]; 6 7 int main(void) 8 { 9 //freopen("Bin.txt", "r", stdin);10 int n, a, b;11 scanf("%d", &n);12 for(int i = 0; i < n; ++i)13 {14 scanf("%d%d", &a, &b);15 right[a] = b;16 left[b] = a;17 cnt[a]++;18 cnt[b]++;19 }20 if(n % 2 == 0)21 {22 int t = 0;23 for(int i = 2; i <= n; i += 2)24 {25 ans[i] = right[t];26 t = right[t];27 }28 t = 0;29 for(int i = n-1; i >= 1; i -= 2)30 {31 ans[i] = left[t];32 t = left[t];33 }34 }35 else36 {37 int i, t = 0;38 for(i = 2; i <= n; i += 2)39 {40 ans[i] = right[t];41 vis[t] = 1;42 t = right[t];43 }44 for(i = 1; i <= maxn; ++i)45 if(cnt[i] == 1) break;46 t = i;47 if(left[t] == 0)48 {49 for(int i = 1; i <= n; i += 2)50 {51 ans[i] = t;52 t = right[t];53 }54 }55 else56 {57 for(int i = n; i >= 1; i -= 2)58 {59 ans[i] = t;60 t = left[t];61 }62 }63 }64 for(int i = 1; i < n; ++i) printf("%d ", ans[i]);65 printf("%d\n", ans[n]);66 67 return 0;68 }
又去翻了翻牛牛们的代码,发现他没有分奇偶,直接输出的,只弄明白大意。
1 #include2 3 using namespace std; 4 5 const int MAXN = 200010; 6 const int MAXA = 1000010; 7 8 int nex[MAXN]; 9 int rb[MAXA], ra[MAXA];10 int a[MAXN], b[MAXN];11 12 int main()13 {14 //freopen("Bin.txt", "r", stdin);15 ios_base::sync_with_stdio(false);16 int n;17 cin >> n;18 int st = -1, stid = -1;19 for (int i = 1; i <= n; i++)20 {21 cin >> a[i] >> b[i];22 ra[a[i]] = i;23 rb[b[i]] = i;24 if (a[i] == 0)25 st = i;26 }27 for (int i = 1; i <= n; i++)28 if (rb[a[i]] == 0)29 stid = a[i];30 while (st != 0)31 {32 cout << stid << " ";33 int nid = b[st];34 st = ra[stid];35 stid = nid;36 }37 cout << endl;38 }
C: (高精度取模)
题意:
有一个大数s和两个int a、b,问是否能够将这个大数从中间分隔开,使得前面的数被a整除,后面的数被b整除,且不能有前导0。
分析:
从低位到高位计算低i位数模b的余数,然后从高位到低位计算高i位数模a的余数,如果有一个i的值满足前i位数被a整除后面的数被b整除且b不含前导0,这找到符合要求的分割,输出即可。
s.substr(pos, len)是求s的从pos开始,长度为len的子串。
1 #include2 #include 3 #include 4 using namespace std; 5 6 const int maxn = 1000000 + 10; 7 int mas[maxn]; 8 9 int main()10 {11 //freopen("Cin.txt", "r", stdin);12 ios::sync_with_stdio(false);13 string s;14 int a, b;15 cin >> s >> a >> b;16 int tmp = 1;17 mas[s.size()] = 0;18 for(int i = (int)s.size()-1; i >= 0; --i)19 {20 mas[i] = mas[i+1] + tmp * (s[i] - '0');21 mas[i] = mas[i] % b;22 tmp *= 10;23 tmp = tmp % b;24 }25 26 tmp = 0;27 for(int i = 0; i < (int)s.size()-1; ++i)28 {29 tmp = tmp * 10 + (s[i] - '0');30 tmp %= a;31 if(tmp == 0 && s[i+1] != '0') //²»ÄÜÓÐÇ°µ¼0 32 {33 if(mas[i+1] == 0)34 {35 cout << "YES\n";36 cout << s.substr(0, i+1) << "\n";37 cout << s.substr(i+1, s.size()-i-1) << "\n";38 return 0;39 }40 }41 }42 cout << "NO\n";43 44 return 0;45 }