【蒻爆了的NOIP系列--普及组复赛】(2)NOIP2011普及组复赛题解
2016-09-03 19:38
597 查看
这只是一个作业,如果有帮到您的,我只能说。。。这不科学。。。
————————————华丽的分割线————————————
第一题:
很有趣的一道题。。。经典做法是字符串读入去头尾0记符号然后乱搞。。。不过我又机智的发明了膜(模)法。。。
下面是代码(主程序巨短)
————————————华丽的分割线————————————
第二题:
又是一道恶心死人的字符串题。。。首先我们要把他们全改成小写。。。
推荐语句:
然后遇到空格就一个字一个字判 把。。。
不过注意判完还要判下一个是不是空格。。
要不然像这个数据:
就狗了
下面是程序
————————————华丽的分割线————————————
第三题:
经典的瑞士轮,这道题一开始第一个思路就是每轮进行操作然后sort一遍
不过要是这样子,数据会让你刚好T掉。。。
所以我们需要常数优化~~~~
怎么优化呢?
首先可以看到每轮操作后每个选手分数要么+1要么不变
于是愉快的使用归并排序
a辣!!!
代码:
————————————华丽的分割线————————————
第四题:
这题很。。。恶心。。。
首先本人第一个想法是把算式用加号分开然后遇到括号拆掉继续递归。。。
然后发现没办法算方案数就。。。
第二个方法:dp
听学长讲这是dp?qwq
这道题的正解原来是这样纸的。。。
首先把表达式加_并转后缀
然后dp。。。
首先用一个栈,每遇到一个数就入栈,遇到运算符把栈顶删了dp
状态:f[i][j]表示栈顶为i时答案为j的方案数
另外遇到数入栈时可能会覆盖原来的答案但是没卵用。
状态转移方橙:
遇到+:
遇到乘相反qwq
就完结了。。。
代码巨长:
(这个程序是学神写的我只是找了些错误。。。)
————————————华丽的分割线————————————
xiaoyao24256大学神访问量过40^2辣!!!膜膜膜
————————————华丽的分割线————————————
第一题:
很有趣的一道题。。。经典做法是字符串读入去头尾0记符号然后乱搞。。。不过我又机智的发明了膜(模)法。。。
下面是代码(主程序巨短)
#include <cstdio> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <ctime> #include <algorithm> #include <queue> #include <map> #define ci const int #define ri register int #define ll long long #define reg register #define boom return #define cmax(a,b) (a)>(b)?(a):(b) #define cmin(a,b) (a)<(b)?(a):(b) #define For(i,a,b) for(i=a;i<b;i++) using namespace std; int a; int main() { int i; scanf("%d",&a); while(!(a%10))a/=10; if(a<0)printf("-"); while(a!=0)printf("%d",abs(a%10)),a/=10; boom 0; } //没有什么是两个巴掌不能解决的,如果有就再来两个巴掌
————————————华丽的分割线————————————
第二题:
又是一道恶心死人的字符串题。。。首先我们要把他们全改成小写。。。
推荐语句:
for(i=0;i<wlen;i++)if(word[i]>='A'&&word[i]<='Z')word[i]+=32; for(i=0;i<slen;i++)if(sen[i]>='A'&&sen[i]<='Z')sen[i]+=32;
然后遇到空格就一个字一个字判 把。。。
不过注意判完还要判下一个是不是空格。。
要不然像这个数据:
To To be or not tobeisaquestion
就狗了
下面是程序
#include <cstdio> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <ctime> #include <algorithm> #include <queue> #include <map> #define ci const int #define ri register int #define ll long long #define reg register #define boom return #define cmax(a,b) (a)>(b)?(a):(b) #define cmin(a,b) (a)<(b)?(a):(b) #define For(i,a,b) for(i=a;i<b;i++) using namespace std; int wlen,slen,ans,first=-1; char word[15],sen[1000086]; int pd(int i) { int j; for(j=0;j<wlen;j++) if(word[j]!=sen[i+j])return 0; return ((sen[i+j]==' '||sen[i+j]=='\0')?1:0); } int main() { int i; gets(word),gets(sen); wlen=strlen(word),slen=strlen(sen); for(i=0;i<wlen;i++)if(word[i]>='A'&&word[i]<='Z')word[i]+=32; for(i=0;i<slen;i++)if(sen[i]>='A'&&sen[i]<='Z')sen[i]+=32; // for(i=0;i<wlen;i++)printf("%d ",word[i]);printf("\n"); // for(i=0;i<slen;i++)printf("%d ",sen[i]);printf("\n"); for(i=0;i<slen&&(sen[i]<'a'||sen[i]>'z');i++); if(pd(i)){ans++;if(first<0)first=i;} for(;i<slen-wlen-1;i++) { if(sen[i]==' '&&pd(i+1)) { ans++; if(first<0)first=i+1; } } if(first<0)printf("-1"); else printf("%d %d",ans,first); boom 0; } //没有什么是两个巴掌不能解决的,如果有就再来两个巴掌
————————————华丽的分割线————————————
第三题:
经典的瑞士轮,这道题一开始第一个思路就是每轮进行操作然后sort一遍
不过要是这样子,数据会让你刚好T掉。。。
所以我们需要常数优化~~~~
怎么优化呢?
首先可以看到每轮操作后每个选手分数要么+1要么不变
于是愉快的使用归并排序
a辣!!!
代码:
#include <cstdio> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <ctime> #include <algorithm> #include <queue> #include <map> #define ci const int #define ri register int #define ll long long #define reg register #define boom return #define cmax(a,b) (a)>(b)?(a):(b) #define cmin(a,b) (a)<(b)?(a):(b) #define For(i,a,b) for(i=a;i<b;i++) using namespace std; ci MAXN=200086; struct Player { int num,s,w; }a[MAXN],b[MAXN],ans[MAXN]; int n,r,q; bool pd(Player a,Player b) {return (a.s==b.s)?(a.num<b.num):(a.s>b.s);} void solve() { int x=1,y=1,z; for (z=1;z<=n*2;z+=2) if (ans[z].w>ans[z+1].w)ans[z].s++,a[x++]=ans[z],b[y++]=ans[z+1]; else ans[z+1].s++,a[x++]=ans[z+1],b[y++]=ans[z]; int i=1,j=1,k=1; while(i<x&&j<y) if(pd(a[i],b[j]))ans[k++]=a[i++]; else ans[k++]=b[j++]; while(i<x)ans[k++]=a[i++]; while(j<y)ans[k++]=b[j++]; } int main() { int i; scanf("%d%d%d",&n,&r,&q); for(i=1;i<=n*2;i++) scanf("%d",&ans[i].s),ans[i].num=i; for (i=1;i<=n*2;i++)scanf("%d",&ans[i].w); sort(ans+1,ans+1+2*n,pd); for (i=1;i<=r;i++)solve(); printf("%d\n",ans[q].num); return 0; } //没有什么是两个巴掌不能解决的,如果有就再来两个巴掌
————————————华丽的分割线————————————
第四题:
这题很。。。恶心。。。
首先本人第一个想法是把算式用加号分开然后遇到括号拆掉继续递归。。。
然后发现没办法算方案数就。。。
第二个方法:dp
听学长讲这是dp?qwq
这道题的正解原来是这样纸的。。。
首先把表达式加_并转后缀
然后dp。。。
首先用一个栈,每遇到一个数就入栈,遇到运算符把栈顶删了dp
状态:f[i][j]表示栈顶为i时答案为j的方案数
另外遇到数入栈时可能会覆盖原来的答案但是没卵用。
状态转移方橙:
遇到+:
f[top-1][1] = (f[top][0] * f[top-1][1] + f[top][1] * f[top-1][0] + f[top][1] * f[top-1][1])%10007; f[top-1][0] = (f[top][0] * f[top-1][0]) % 10007;
遇到乘相反qwq
就完结了。。。
代码巨长:
#include <cstdio> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <ctime> #include <algorithm> #include <queue> #include <map> #include <stack> #define ci const int #define ri register int #define ll long long #define reg register #define boom return #define cmax(a,b) (a)>(b)?(a):(b) #define cmin(a,b) (a)<(b)?(a):(b) #define For(i,a,b) for(i=a;i<b;i++) using namespace std; ci MAXN=100086; int i,j,n,m,f[MAXN][2]; string s,w_c; char str[MAXN],first[3]={'(','+','*'}; stack<char> op; int OPS(char a) { int i; for(i=0;i<3;i++)if(a==first[i])return i; return -1; } inline void Change() { int i; char t; for(i=0;i<n;i++) { if(str[i] == '(') s.push_back(str[i]); else if(str[i] == ')' && str[i-1] != ')') s+="_)"; else if(str[i]!=')' && str[i-1] != ')') { s.push_back('_'); s.push_back(str[i]); } else s.push_back(str[i]); } if(s.at(s.size()-1)!=')') s.push_back('_'); for(i=0;i<s.size();i++) { t=s.at(i); if(t=='_')w_c.push_back(t); else { if(t!=')') { if(t=='(')op.push(t); else { if(op.empty())op.push(t); else { while((!op.empty())&& OPS(op.top())>=OPS(t)) w_c.push_back(op.top()),op.pop(); op.push(t); } } } else { while((!op.empty()) && op.top()!='(') w_c.push_back(op.top()),op.pop(); op.pop(); } } } while(!op.empty()) w_c.push_back(op.top()),op.pop(); } void work() { size_t i,top(0); size_t l=w_c.size(); for(i=0;i<l;i++) { if(w_c[i]=='_')f[top][0]=f[top][1]=1,top++; else { --top; switch(w_c[i]) { case '+': { f[top-1][1] = (f[top][0] * f[top-1][1] + f[top][1] * f[top-1][0] + f[top][1] * f[top-1][1])%10007; f[top-1][0] = (f[top][0] * f[top-1][0]) % 10007; break; } case '*': { f[top-1][0] = (f[top][0] * f[top-1][1] + f[top][1] * f[top-1][0] + f[top][0] * f[top-1][0])%10007; f[top-1][1] = (f[top][1] * f[top-1][1]) % 10007; break; } } } } printf("%d",f[top-1][0]); } int main(){ scanf("%d",&n); scanf("%s",str); Change(); work(); return 0; } //没有什么是两个巴掌不能解决的,如果有就再来两个巴掌
(这个程序是学神写的我只是找了些错误。。。)
————————————华丽的分割线————————————
xiaoyao24256大学神访问量过40^2辣!!!膜膜膜
相关文章推荐
- 【用膝盖写代码系列】(2):NOIP2011普及组复赛题目详解
- 【蒻爆了的NOIP系列--普及组复赛】(4)NOIP2013普及组复赛题解
- 【蒻爆了的NOIP系列--普及组复赛】(5)NOIP2014普及组复赛题解
- 【用膝盖写代码系列】(2):NOIP2011普及组复赛详解
- 【蒻爆了的NOIP系列--普及组复赛】(3)NOIP2012普及组复赛题解
- 【用膝盖写代码系列】(4):NOIP2014普及组复赛详解
- NOIP2016普及组复赛第一题的ACC程序加题解pascal
- NOIP2011-普及组复赛-第一题-数字反转
- NOIP2011-普及组复赛-第二题-统计单词数
- noip2011普及组复赛——数字反转
- NOIP2011-普及组复赛模拟试题-第一题-NBA总冠军
- NOIP 2011 普及组 复赛 swiss 瑞士轮
- NOIP 2011 普及组 复赛 reverse 数字反转
- NOIP2017普及组复赛题解
- NOIP 2011 普及组 复赛 stat 统计单词数
- 【蒻爆了的NOIP系列--普及组复赛】(1)NOIP2010普及组复赛题解
- 【用膝盖写代码系列】(5):NOIP2013普及组复赛详解
- 【用膝盖写代码系列】(1):NOIP2010普及组复赛详解
- NOIP2016普及组复赛第二题60分程序加题解pascal大神求帮忙!!!———回文日期
- NOIP-2016-普及组 复赛题解