1.数字反转

算法分析

反转后需要考虑前导0。重新组数就可以规避这个问题。就是剥数和组数的过程。

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
int main()
{int n;scanf("%d", &n);if (n < 0){n = -n;printf("-");}int x = 0;while (n){x = x * 10 + n % 10;n /= 10;}printf("%d\n", x);return 0;
}

2.统计单词数

算法分析

题目没有说文章中单词距离单词有多少空格,实际上有的数据点,第一个单词前就有空格。读取一整行带空格的字符串,可以考虑用stringstringstring类型的getlinegetlinegetline。这道题的数据推测是windows下造的,用不了getchargetchargetchar。

读完后,对于文章的位置一个个的和单词进行比对判断。文章中开始比对的字符,它前面和后面得是空格。特殊情况是:第一个和最后一个字符。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define ll long long
using namespace std;
int t;
string s, s1;
int scmp(int i)
{int n = i + t - 1, j = 0;while (i <= n){if(s1[i] != s[j]) return 0;++i;++j;}return 1;
}
int main()
{getline(cin, s);t = s.length();for (int i = 0; i < t; ++i) if (s[i] >= 'A' && s[i] <= 'Z') s[i] += 32;getline(cin, s1);int n = s1.length();for (int i = 0; i < n; ++i) if (s1[i] >= 'A' && s1[i] <= 'Z') s1[i] += 32;int cnt = 0, spos;for (int i = 0; i <= n; ++i){if (s1[i] == 32) continue;if ((i - 1 == -1 ? 1 : s1[i-1] == 32) && scmp(i) && (i + t - 1 == n ? 1 : s1[i+t] == 32)){++cnt;if (cnt == 1) spos = i;}}if (!cnt) printf("-1\n"); else printf("%d %d\n", cnt, spos);return 0;
}

3.瑞士轮

算法分析

每轮比赛结束后,需要重新排序。这个过程不能用sort,时间复杂度太大。观察得出,对于获胜的一方和失败的一方,他们都是有序的,也就是我们需要对两个有序的序列重新排序,借鉴归并排序中最后合并的思想。每次排序是O(n)O(n)O(n)的复杂度,需要排RRR次。整体时间复杂度O((nlogn+Rn))O((nlogn+Rn))O((nlogn+Rn))。

#include <cstdio>
#include <iostream>
#include<algorithm>
using namespace std;
int n;
struct node
{int num,score,power;
};
node a[200010],win[100010],lost[100010];
inline bool cmp(node a,node b)
{if(a.score==b.score) return a.num<b.num;else return a.score>b.score;
}
void solve()
{int lenwin=0,lenlost=0;for(int i=1;i<=2*n;i+=2){if(a[i].power>a[i+1].power){a[i].score+=1;win[++lenwin]=a[i];lost[++lenlost]=a[i+1];}else{a[i+1].score+=1;win[++lenwin]=a[i+1];lost[++lenlost]=a[i];}}//int i=1,j=1,k=1;while(i<=lenwin&&j<=lenlost){if(win[i].score==lost[j].score){if(win[i].num<lost[j].num) a[k]=win[i],++k,++i;else a[k]=lost[j],++k,++j;} else if(win[i].score>lost[j].score) a[k]=win[i],++k,++i;else a[k]=lost[j],++k,++j;}while(i<=lenwin) a[k]=win[i],++k,++i;while(j<=lenlost) a[k]=lost[j],++k,++j;
}
int main()
{int r,q,x;scanf("%d%d%d",&n,&r,&q);for(register int i=1;i<=2*n;++i){scanf("%d",&x);a[i].num=i;a[i].score=x;}for(register int i=1;i<=2*n;++i){scanf("%d",&x);a[i].power=x;}sort(a+1,a+2*n+1,cmp);for(register int i=1;i<=r;++i){solve();}printf("%d\n",a[q].num);return 0;
}

4.表达式的值

算法分析

类似于中缀表达式求值。这题求的是方案数。用递归,dfs(l,r)dfs(l, r)dfs(l,r)求的是区间[l,r][l, r][l,r]为0的方案数。整体思路:从右往左扫描,找到括号外的第一个加号,返回左右两个区间相乘的结果。如果没有加号,则找到括号外的第一个乘号,如果左侧是0,则右侧怎么填结果都是0,假设此时右侧的加号和乘号总数为cnt,则右侧的方案为2cnt+12^{cnt+1}2cnt+1;如果右侧是0,则左侧怎么填结果都是0,假设此时左侧的加号和乘号总数为cnt,则左侧的方案为2cnt+12^{cnt+1}2cnt+1。此时多加了一个0∗00*00∗0的情况,再减去。无论是加号还是乘号,都需要特判符号在边缘的情况。

递归过程中的一些优化细节:

1.前缀和维护区间里加号和乘号的个数。

2.利用栈来维护每个右括号对应的左括号,在递归中,首先判断左右边界是不是相匹配的括号,如果是,则边界缩减。

3.不要重复计算。

4.ans%pans \% pans%p可能为负,但是(ans%p+p)%p(ans \% p + p) \% p(ans%p+p)%p一定为正。

这是道练习递归的好题。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#define ll long long
using namespace std;
const int P = 10007;
int n, sum[100010];
char s[100010];
stack<int> sstack;
int spi[100010]; // 记录右括号匹配的左括号
int smi[100010]; // 2的i次方mod P
ll dfs(int l, int r)
{while (s[r] == ')' && spi[r] == l){++l; --r;}if (l == r && s[l] == '*') return 3;if (l == r && s[l] == '+') return 1;// 找括号外从右往左的第一个+和* int posjia = 0, poscheng = 0, kh = 0; // kh:括号的个数  // for (int i = r; i >= l; --i){if (s[i] == ')'){i = spi[i]; // 直接跳到对应的左括号处 continue; }if (s[i] == '+' && posjia == 0 && kh == 0) posjia = i;if (s[i] == '*' && poscheng == 0 && kh == 0) poscheng = i;if (posjia) break;} if (posjia){if (posjia == l) return dfs(posjia+1, r) % P;else if (posjia == r) return dfs(l, posjia-1) % P;else return (dfs(l, posjia-1) % P * dfs(posjia+1, r) ) % P;}else if (poscheng){int cnt1 = sum[poscheng-1] - sum[l-1], cnt2 = sum[r] - sum[poscheng];ll ans = 0;if (poscheng == l) return (smi[cnt2+1] + dfs(poscheng+1, r) % P) % P;else if (poscheng == r) return (smi[cnt1+1] + dfs(l, poscheng-1) % P) % P;else{ll ans1 = dfs(l, poscheng-1) % P;ll ans2 = dfs(poscheng+1, r) % P;ans += (smi[cnt1+1] * ans2 ) % P;      ans += (ans1 * smi[cnt2+1]) % P; // 多加了左右都是0的情况,减去  ans -= (ans1 * ans2 ) % P;return (ans + P) % P;  // 防止变成负数,重要  }     }
}
int main()
{//  freopen("P1310_2.in", "r", stdin);scanf("%d", &n);scanf("%s", s + 1);for (int i = 1; i <= n; ++i)if (s[i] == '*' || s[i] == '+') sum[i] = sum[i-1] + 1;else sum[i] = sum[i-1];// spiint stop;for (int i = 1; i <= n; ++i)if (s[i] == '(') sstack.push(i);else if (s[i] == ')'){stop = sstack.top(); sstack.pop();spi[i] = stop; // 位置i的右括号匹配的左括号的位置  }smi[0] = 1;for (int i = 1; i <= n; ++i) smi[i] = smi[i-1] * 2 % P;printf("%lld\n", dfs(1, n));return 0;
}

NOIP2011普及组复赛 解题分析相关推荐

  1. NOIP2015普及组复赛 解题分析

    1.金币 算法分析 直接模拟. #include <iostream> #include <cstdio> #include <cstring> using nam ...

  2. C语言普及组NOIP考试培训,NOIP 2018普及组复赛解题报告来了!

    以下解题思路及选手代码未经官方评测,仅供参考,复赛成绩以官方(CCF)评测结果为准. 主要考察字符串.参考代码: #include int main() { int ans = 0; char ch; ...

  3. 信息学奥赛一本通 1956:【11NOIP普及组】表达式的值 | 洛谷 P1310 [NOIP2011 普及组] 表达式的值

    [题目链接] ybt 1956:[11NOIP普及组]表达式的值 洛谷 P1310 [NOIP2011 普及组] 表达式的值 [题目考点] 表达式树 由带括号的中缀表达式构建表达式树 [解题思路] 思 ...

  4. 信息学奥赛一本通 1089:数字反转 | 1953:【11NOIP普及组】数字反转 | OpenJudge NOI 1.5 29 | 洛谷 P1307 [NOIP2011 普及组] 数字反转

    [题目链接] ybt 1089:数字反转 ybt 1953:[11NOIP普及组]数字反转 OpenJudge NOI 1.5 29:数字反转 洛谷 P1307 [NOIP2011 普及组] 数字反转 ...

  5. 近年NOIP普及组复赛题目的简单讲解

    NOIP2015普及组复赛 整套题都出得不错,难度适中,层次分明 建议同学们在做题的时候还是先在草稿纸上分析,把关键算法的伪代码写出来,然后设计数据进行静态查错,没有问题后再到电脑上敲出代码.实际效率 ...

  6. 信息学奥赛一本通 1400:统计单词数 | 1954:【11NOIP普及组】统计单词数 | OpenJudge NOI 1.12 05 | 洛谷 P1308 [NOIP2011 普及组] 统计单词数

    [题目链接] ybt 1400:统计单词数 ybt 1954:[11NOIP普及组]统计单词数 OpenJudge NOI 1.12 05:统计单词数 洛谷 P1308 [NOIP2011 普及组] ...

  7. 信息学奥赛一本通 1955:【11NOIP普及组】瑞士轮 | OpenJudge NOI 4.1 4363:瑞士轮 | 洛谷 P1309 [NOIP2011 普及组] 瑞士轮

    [题目链接] ybt 1955:[11NOIP普及组]瑞士轮 OpenJudge NOI 4.1 4363:瑞士轮 洛谷 P1309 [NOIP2011 普及组] 瑞士轮 [题目考点] 1. 归并排序 ...

  8. P1307 [NOIP2011 普及组] 数字反转(python3实现)

    https://www.luogu.com.cn/problem/P1307 """P1307 [NOIP2011 普及组] 数字反转 https://www.luogu ...

  9. 洛谷——P1307 [NOIP2011 普及组] 数字反转

    P1307 [NOIP2011 普及组] 数字反转 题目描述 给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应 ...

最新文章

  1. Python构建lassocv模型并输出Rad-score公式
  2. HP-UX 六大虚拟化技术之“分区”
  3. vue人员轨迹_在vue中高德地图引入和轨迹的绘制的实现
  4. WEB前端学习六 js什么是闭包
  5. 区块链中密码学与安全技术
  6. Android端发送字符到Wed端,android应用端向web端获取字符串。
  7. Java 进栈出栈的过程
  8. node.js——阿里企业级服务框架Egg搭建
  9. 不知该买哪儿的房?数据分析来为你解答哪儿的房值得买
  10. Red Hat Enterprise Linux的一些简单操作(备忘录)
  11. 《深度学习轻松学》-第8章优化与训练
  12. online_judge_1478
  13. YOLOv4 绘制PR曲线
  14. 三阶魔方复原操作方法
  15. 鸿蒙5G的营业执照,华为鸿蒙系统疑似被曝光 工信部向三大运营商颁发5G牌照​...
  16. 搬运:PHOTOSHOP存储为 Web 所用格式的选项|处理PNG图像透明度时的仿色选项
  17. 【修改电脑版微信提示音】
  18. codeforces1567B
  19. Spring mcv 框架 浅谈
  20. xdos攻击ac实验环境

热门文章

  1. 鸿蒙系统怎么退出,华为鸿蒙2.0系统升级了怎么退回EMUI11系统?操作教程详解[多图]...
  2. Unity——Tolua框架笔记
  3. 饿了?饿了么?3年工作经验的程序员天天点外卖决定投声了饿了么面经!
  4. 树洞外链更新至2.2-支持本地/远程储存,新增用户系统
  5. Charles抓包APP
  6. java调用c/c++
  7. 数据库显示受限制用户
  8. Vue 路由 导航守卫(全局守卫、路由独享守卫、组件内守卫)
  9. 医院his系统 源代码_中药煎配中心运营指南⑤ | 中药煎配中心如何接收医院处方...
  10. 学习笔记之抽取和内插