题目链接
官方题解
设 a,e,i,o,u,y a , e , i , o , u , y 是六个特殊字母,如果一个小写字母串从左往右读,出现连续两个特殊字母时,则删除后面这个特殊字母,直至没有连续两个特殊字母,输出这样处理后的字符串。
按照题意模拟即可: i i 表示将要输出的字母, j j 表示下一个可能会输出的字母
①如果 i,j i , j 都是特殊字母,则 i i 不变,令 j j 变为下一个字母
②如果 i,j i , j 至少有一个不是特殊字母,则输出 i i ,然后令 i=j i = j , j j 变为下一个字母
#include
#include
#include
using namespace std;
const int MAXN = 103;
int n;
char s[MAXN];
inline bool isVowel(char ch) {
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'y';
}
int main() {
while(2 == scanf("%d%s", &n, s)) {
for(int i = 0, j = 1; i < n;) {
if(isVowel(s[i]) && isVowel(s[j])) {
++j;
}
else {
printf("%c", s[i]);
i = j;
if(j < n) {
++j;
}
}
}
printf("\n");
}
}
在一条数轴上坐标为 2∼106−1 2 ∼ 10 6 − 1 范围内有 n n 个奖品,甲可以从坐标为 1 1 的位置开始拿奖品,乙可以从坐标为 106 10 6 的位置开始拿奖品,两人每移动一个单位距离需要 1 1 秒,拿奖品不耗时,求两人把所有奖品拿完的最短耗时?
枚举相邻的两个奖品(左边分别为 i,j i , j ),甲拿前者及其左边的奖品,乙拿后者及其右边的奖品,则总耗时为 max(i−1,106−j) m a x ( i − 1 , 10 6 − j ) ,取最小值。注意边界值,及甲或者乙不拿奖品的时候。
#include
#include
#include
using namespace std;
const int END = 1e6;
int n;
int last, cur, ans;
int main() {
while(1 == scanf("%d", &n)) {
ans = END;
last = 0;
while(n-- > 0) {
scanf("%d", &cur);
ans = min(ans, max(END - cur, last - 1));
last = cur;
}
ans = min(ans, last - 1);
printf("%d\n", ans);
}
}
设一个 n n 阶 01 01 方阵,若其每一个 m m 阶子方阵内都至少含有一个 0 0 ,此时这个 n n 阶方阵内最多能有 k k 个 1 1 。现在给定 k k ,构造 n,m n , m 使其满足上述条件,无法构造则输出 −1 − 1 。
用将 n n 阶方阵划分成不重叠的 m m 阶方阵,不够的不计算,则共能划分成 ⌊nm⌋2 ⌊ n m ⌋ 2 个完整的 m m 阶方阵,每个方阵右下角取 0 0 ,其全为 1 1 ,则能满足题意。从而得到关系: n2−⌊nm⌋2=k n 2 − ⌊ n m ⌋ 2 = k 。
又: m=1 m = 1 时, k k 横为 0 0 ,且 n n 不变时, k k 随着 m m 的递增而非递减,可知对于每一个 n n , k k 的下界为 3n24 3 n 2 4 ,从而由 k k 得到 n n 的上界为 4k3−−√ 4 k 3 ,所以枚举 n n ,然后计算得 m m ,再判断 n,m,k n , m , k 是否满足得到的关系即可。
#include
#include
#include
#include
using namespace std;
const double EPS = 1e-6;
int x;
int main() {
int T;
scanf("%d", &T);
while(T-- > 0) {
scanf("%d", &x);
if(x == 0) {
printf("1 1\n");
continue;
}
bool flag = false;
for(int n = 2; ((3LL * n * n) >> 2LL) <= x; ++n) {
long long tmp = 1LL * n * n - x;
if(tmp > 0) {
int n_m = sqrt(tmp) + EPS;
int m = n / n_m;
if(n * n - (n / m) * (n / m) == x) {
printf("%d %d\n", n, m);
flag = true;
break;
}
}
}
if(!flag) {
printf("-1\n");
}
}
}
给定一个 n n 个顶点, m m 条边的无向图,每条边都有权值 w w ,每个顶点有权值 a a ,对于每一个顶点 i i 找出一个顶点 j j ( i i 到 j j 的最短路径为 dist d i s t , j j 的权值为 x x ),使得: 2dist+x 2 d i s t + x 最小。
设置一个超级源点,其到每个顶点都有条无向边,权值为该顶点的权值,则问题转化为单元最短路,直接用堆优化的 Dijkstra D i j k s t r a 即可。
#include
#include
#include
#include
using namespace std;
const int MAXN = 200003;
const int MAXM = 200003;
struct Node {
int v;
long long w;
Node() {}
Node(int v, long long w):v(v), w(w) {}
bool operator< (const Node& a) const {
return w > a.w;
}
};
struct Edge {
int v, nxt;
long long w;
}edge[(MAXM + MAXN) << 1];
int tot, fir[MAXN];
void init() {
tot = 0;
memset(fir, -1, sizeof(fir));
}
void addEdge(int u, int v, long long w) {
edge[tot].v = v;
edge[tot].w = w;
edge[tot].nxt = fir[u];
fir[u] = tot++;
edge[tot].v = u;
edge[tot].w = w;
edge[tot].nxt = fir[v];
fir[v] = tot++;
}
int n, m;
long long a;
long long dist[MAXN];
bool vis[MAXN];
void dijkstra() {
memset(vis, false, sizeof(vis));
memset(dist, 0x3f, sizeof(dist));
dist[0] = 0;
priority_queue q;
q.push(Node(0, dist[0]));
int u, v;
long long w;
Node cur;
while(!q.empty()) {
cur = q.top();
u = cur.v;
w = cur.w;
q.pop();
if(vis[u]) {
continue;
}
vis[u] = true;
for(int i = fir[u]; i != -1; i = edge[i].nxt) {
v = edge[i].v;
w = edge[i].w;
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
q.push(Node(v, dist[v]));
}
}
}
}
int main() {
int u, v;
long long w;
while(2 == scanf("%d%d", &n, &m)) {
init();
while(m-- > 0) {
scanf("%d%d%I64d", &u, &v, &w);
addEdge(u, v, w << 1LL);
}
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &a);
addEdge(0, i, a);
}
dijkstra();
for(int i = 1;i <= n; ++i) {
printf("%I64d%c", dist[i], i == n ? '\n' : ' ');
}
}
}