A
最大连续的存在0字符子串个数。
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
int n, d;
while(scanf("%d%d", &n, &d) != EOF) {
int l = 0, ans = 0;
for(int i = 0; i < d; i++) {
char str[110];
scanf("%s", str);
bool flag = false;
for(int j = 0; j < n; j++) {
if(str[j] == '0') {
flag = true; break;
}
}
if(flag) {
ans = max(ans, i - l + 1);
}
else {
l = i+1;
}
}
printf("%d\n", ans);
}
return 0;
}
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string a;
while(cin >> a) {
cout << a;
reverse(a.begin(), a.end());
cout << a << endl;
}
return 0;
}
C
题意::给定一个图,可能非联通,让你将它划分为两个集合。说白了就是——划分成二分图。
思路:先DFS,然后黑白染色。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 1e5 + 10;
vector<int> G[MAXN];
int color[MAXN], in[MAXN];
bool judge(int u) {
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(color[u] == color[v]) return false;
if(!color[v]) {
color[v] = 3 - color[u];
if(!judge(v)) return false;
}
}
return true;
}
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF) {
for(int i = 1; i <= n; i++) {
G[i].clear(); color[i] = in[i] = 0;
}
for(int i = 0; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
in[u]++; in[v]++;
}
bool flag = true;
for(int i = 1; i <= n; i++) {
if(in[i] && color[i] == 0) {
color[i] = 1;
flag &= judge(i);
if(!flag) break;
}
}
if(!flag) {
printf("-1\n");
}
else {
int cnt1 = 0, cnt2 = 0;
for(int i = 1; i <= n; i++) {
cnt1 += color[i] == 1;
cnt2 += color[i] == 2;
}
printf("%d\n", cnt1);
int cnt = 0;
for(int i = 1; i <= n; i++) {
if(color[i] == 1) {
if(cnt > 0) printf(" ");
printf("%d", i);
cnt++;
}
}
printf("\n%d\n", cnt2);
cnt = 0;
for(int i = 1; i <= n; i++) {
if(color[i] == 2) {
if(cnt > 0) printf(" ");
printf("%d", i);
cnt++;
}
}
printf("\n");
}
}
return 0;
}
题意比较晦涩吧,总之最后就是判断lcm(a[1],…,a[n]) % k == 0。
两种方法
一、每次记录v最大的质因子,这样求出v的质因子时间复杂度是log(v),下面用快速幂求一次就好了。
二、比较神奇,lcm(gcd(a[1], k),…,gcd(a[n], k)) == k。
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 10;
LL pow_mod(LL a, LL n, LL k) {
LL ans = 1;
while(n) {
if(n & 1) {
ans = ans * a % k;
}
a = a * a % k;
n >>= 1;
}
return ans;
}
int cnt[MAXN];
int pre[MAXN];
int main()
{
for(int i = 2; i <= 1000000; i++) {
if(!pre[i]) {
pre[i] = i;
for(int j = 2 * i; j <= 1000000; j += i) {
pre[j] = i;
}
}
}
int n, k;
while(scanf("%d%d", &n, &k) != EOF) {
memset(cnt, 0, sizeof(cnt));
int Max = 0;
for(int i = 1; i <= n; i++) {
int v; scanf("%d", &v); Max = max(Max, v);
while(v > 1) {
int p = pre[v]; int num = 0;
while(v % p == 0) {
v /= p;
num++;
}
cnt[p] = max(cnt[p], num);
}
if(v > 1) {
cnt[v] = max(cnt[v], 1);
}
}
LL ans = 1LL % k;
for(int i = 2; i <= Max; i++) {
if(cnt[i]) {
ans = ans * pow_mod(i, cnt[i], k) % k;
}
}
printf(ans == 0 ? "Yes\n" : "No\n");
}
return 0;
}
E
题意:给定n个数,你需要选出某个集合使集合内元素之和等于k。问所有合法集合可以得到的数(可以让集合内元素相加)。
思路:明显的dp,而且数据范围正好是时间复杂度可以承受的。
dp[i][j][k]
表示前i个数(包括第i个数)选出某个集合元素之和为k且该集合可以得到j。合法为true,反之false。
这样时间复杂度是
O(n∗k∗k)
。
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <set>
#include <cstring>
using namespace std;
bool dp[2][501][501];
int a[501];
int main()
{
int n, sum;
while(scanf("%d%d", &n, &sum) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
memset(dp, false, sizeof(dp));
bool id = 0;
dp[id][a[1]][0] = dp[id][a[1]][a[1]] = true;
for(int i = 1; i < n; i++) {
dp[!id][a[i+1]][a[i+1]] = true;
dp[!id][a[i+1]][0] = true;
for(int j = 0; j <= 500; j++) {
for(int k = 0; k <= 500; k++) {
if(dp[id][j][k]) {
dp[!id][j][k] = true;
if(j + a[i+1] <= 500) {
dp[!id][j + a[i+1]][k] = true;
if(k + a[i+1] <= 500) {
dp[!id][j + a[i+1]][k + a[i+1]] = true;
}
}
}
}
}
id = !id;
}
int cnt = 0;
for(int i = 0; i <= 500; i++) {
if(dp[id][sum][i]) {
cnt++;
}
}
printf("%d\n", cnt); int num = 1;
for(int i = 0; i <= 500; i++) {
if(dp[id][sum][i]) {
if(num > 1) printf(" ");
printf("%d", i);
num++;
}
}
if(cnt) printf("\n");
}
return 0;
}