2010 辽宁省省赛 题解
来源:互联网 发布:曹县大集淘宝村现状 编辑:程序博客网 时间:2024/05/01 12:01
题目来源:2010辽宁省省赛
比赛名:NBUT 2012 Weekly - 13th Oct for 11x
题目链接:http://ac.nbutoj.com/Problem.xhtml?page=3 1217~1225
比赛的时候过了8题,H题后来知道是什么了。。但是还是不知道怎么求。。。
A题:水题,字符串比较。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;main(){ int n; while(scanf("%d",&n)!=EOF) { bool flag=1; for(int i=0;i<n;i++) { string c; cin>>c; if(c=="bowl"||c=="knife"||c=="fork"||c=="chopsticks") { if(flag==0) printf(" "); cout<<c; flag=0; } } puts(""); } return 0;}
B题:给一棵树,问树上两个点,哪个的深度小。
直接每次把两个点移动到父节点,记录下他们走过的点,某个点走到另一个点走过的点,说明这个点深度大。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;int fa[2022]={0};int vis1[2022]={0};int vis2[2022]={0};main(){ int n; while(scanf("%d",&n)!=EOF) { clr(fa); clr(vis1); clr(vis2); // clrset(fa,2000); for(int i=0;i<n;i++) { int a,b; scanf("%d%d",&a,&b); fa[a]=b; } vis1[1]=1; vis2[2]=1; int p1=1,p2=2; while(1) { int x2=fa[p1]; int y2=fa[p2]; if(x2==y2) { puts("You are my brother"); break; } else if(vis1[y2]==1) { puts("You are my younger"); break; } else if(vis2[x2]==1) { puts("You are my elder"); break; } else { vis1[x2]=1; vis2[y2]=1; p1=x2; p2=y2; } } // return 0; } return 0;}
C题:给4个1位数字,用计算器的格式输出。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;char cc[3][31]={" _ _ _ _ _ _ _ _ "," | _| _||_||_ |_ ||_||_|| |"," ||_ _| | _||_| ||_| _||_|"};main(){ int a,b,c,d; while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF) { for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { printf("%c",cc[i][(((a-1)+10)%10)*3+j]); } for(int j=0;j<3;j++) { printf("%c",cc[i][(((b-1)+10)%10)*3+j]); } for(int j=0;j<3;j++) { printf("%c",cc[i][(((c-1)+10)%10)*3+j]); } for(int j=0;j<3;j++) { printf("%c",cc[i][(((d-1)+10)%10)*3+j]); } puts(""); } } return 0;D:给三个字符串列表,第一个代表要来A国的人,第二个代表B国的间谍,第三个代表A国派去B国的间谍【也就是A国的人】,问来的人中,B国的间谍有哪些#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;map<string,int>mp;int main(){ int n1,n2,n3; while(scanf("%d%d%d",&n1,&n2,&n3)!=EOF) { string c[10000]; mp.clear(); for(int i=0;i<n1;i++) { string c1; cin>>c1; mp[c1]=1; } for(int i=0;i<n2;i++) { cin>>c[i]; mp[c[i]]++; } for(int i=0;i<n3;i++) { string c1; cin>>c1; mp[c1]--; } bool flag=0; for(int i=0;i<n2;i++) if(mp[c[i]]==2) { if(flag) printf(" "); cout<<c[i]; flag=1; } if(flag==0) { puts("No enemy spy"); } else puts(""); } return 0;}E题:给一个图,图上的每条边都被一个人管理着,每条边有个过路费,第一次经过a管理的路时,只用交过路费,第二次要多交e[a],第三次要多交f[a]。问0~n-1的最少花费的路径。正解应该是状态压缩搜索吧。因为管理者最多有9个,所以我们可以用一个3^9的数代表被管理的道路的状态。dp[i][j]代表到第i个点,状态为j,最少花费为多少,直接记忆化搜索一发应该就行了。。
比赛的时候直接爆搜过了,当时没多想就觉得数据很小有可能爆过去。。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;struct node{ int val; int emp; int to;};vector<node>road[111];int e[11]={0};int f[11]={0};int use[11]={0};int vis[111]={0};int n,m,q;long long minn=INF;void find(int pos,int sum){ if(sum>=minn) return; if(pos==n-1) { minn=sum; return; } for(int i=0;i<road[pos].size();i++) { int next=road[pos][i].to; if(!vis[next]) { vis[next]=1; int k=road[pos][i].emp; int c=road[pos][i].val; use[k]++; if(use[k]==1) find(next,sum+c); else if(use[k]==2) find(next,sum+c+e[k]); else find(next,sum+c+f[k]); vis[next]=0; use[k]--; } }}main(){ while(scanf("%d%d%d",&n,&m,&q)!=EOF) { clr(vis); clr(use); for(int i=0;i<=100;i++) road[i].clear(); for(int i=0;i<m;i++) scanf("%d",e+i); for(int i=0;i<m;i++) scanf("%d",f+i); for(int i=0;i<q;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); node temp; temp.to=b; temp.val=d; temp.emp=c; road[a].push_back(temp); } minn=INF; find(0,0); if(minn==INF) puts("-1"); else printf("%d\n",minn); } return 0;}//爆搜的。。状压的看我心情写不写了。。。F题:给一个字符串,和n个子串,每个子串有一个权值,用子串去填充原串,一个串可以用多次,问填充后最大权值是多少,若不能完全填充输出-1 首先肯定是要DP的,但是因为原串长10000,子串长30,并且有1000个,所以复杂度会有3亿不科学。于是想到用字典树。 将所有串加到字典树中,然后memset(dp,-1,sizeof(dp));,dp[0]=0,之后直接dp,对于每个不为-1的dp值,去查找这个点往后的30个子串是否存在于字典树中,若存在则更新下一个dp值。然后这样会T,有一个优化必须加,往后找子串的时候,假如找到某一个子串,在查找过程中遇到了-1而退出,说明后面的子串肯定都不满足条件,就可以直接退出本次DP。加了之后170ms过。#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;struct node{ int end; int val; int next[26];}trie[50000];int top=1;inline void init(){ trie[0].end=0; trie[0].val=0; for(int i=0;i<26;i++) trie[0].next[i]=-1; top=1;}inline void insert(char *c,int pos,int v){ if(c[0]==0) { trie[pos].end=1; trie[pos].val=v; return; } else if(trie[pos].next[c[0]-'a']!=-1) { insert(c+1,trie[pos].next[c[0]-'a'],v); } else { trie[top].end=0; trie[top].val=0; for(int i=0;i<26;i++) trie[top].next[i]=-1; trie[pos].next[c[0]-'a']=top++; insert(c+1,top-1,v); }}inline int find(char *c,int pos){ if(c[0]==0) { if(trie[pos].end) return trie[pos].val; return -1; } else if(trie[pos].next[c[0]-'a']==-1) return -2; else { return find(c+1,trie[pos].next[c[0]-'a']); }}main(){ int n; while(scanf("%d",&n)!=EOF) { char need[10011]={0}; need[0]='#'; scanf("%s",need+1); int len=strlen(need); int dp[10011]; memset(dp,-1,sizeof(dp)); dp[0]=0; init(); for(int i=0;i<n;i++) { char c[100]={0}; scanf("%s",c); int d; scanf("%d",&d); insert(c,0,d); } for(int i=0;i<len-1;i++) { if(dp[i]==-1) continue; char c[100]={0}; for(int j=0;j<30,i+j+1<len;j++) { c[j]=need[i+j+1]; int x=find(c,0); if(x>=0) { if(dp[i+j+1]<dp[i]+x) dp[i+j+1]=dp[i]+x; } else if(x==-2) break; } } if(dp[len-1]!=-1) printf("%d\n",dp[len-1]); else printf("-1\n"); } return 0;}
G题:问a,b中的亲和数对数直接打表= =。。。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;int aa[1000]={284,1210,2924,5564,6368,10856,14595,18416,76084,66992,71145,87633,88730,124155,139815,123152,153176,168730,176336,180848,203432,202444,365084,389924,430402,399592,455344,486178,514736,525915,669688,686072,691256,712216,652664,783556,796696,863835,901424,980984,1125765,1043096,1099390,1189150,1292570,1438983,1286744,1340235,1483850,1486845,1464592,1747930,1749212,1598470,2062570,1870245,2090656,2429030,2941672,2874064,3077354,2928136,2947216,3716164,3721544,3892670,4300136,4006736,4314616,4488910,4445050};int bb[1000]={220,1184,2620,5020,6232,10744,12285,17296,63020,66928,67095,69615,79750,100485,122265,122368,141664,142310,171856,176272,185368,196724,280540,308620,319550,356408,437456,469028,503056,522405,600392,609928,624184,635624,643336,667964,726104,802725,879712,898216,947835,998104,1077890,1154450,1156870,1175265,1185376,1280565,1328470,1358595,1392368,1466150,1468324,1511930,1669910,1798875,2082464,2236570,2652728,2723792,2728726,2739704,2802416,2803580,3276856,3606850,3786904,3805264,4238984,4246130,4259750};main(){ int a,b; while(scanf("%d%d",&a,&b)!=EOF) { int cnt=0; for(int i=0;i<71;i++) { if(bb[i]>=a&&aa[i]<=b) cnt++; // else if(aa[i]>b) // break; } printf("%d\n",cnt); } return 0;}
H题:解佩尔方程。。。当时就跪了。。想了很久都不会,结果熊教一眼就看出是佩尔方程Orz。。但是还是不会求。。。提供一份代码,以后研究去。。
code by eapink
#include<cstdio>#include<cmath>#include<cstdio>#include<iostream>#include<sstream>#include<vector>using namespace std;int count(string s){ int count=0; for(int i=0;i<s.length();i++) if(s[i]=='0') count++; else break; return count;} string muling(string s1,string s2){ string cheng(s1.length()+s2.length(),'0'); for(int n2=s2.length()-1;n2>=0;n2--) if(s2[n2]) for(int n1=s1.length()-1,n=n2+s1.length();n1>=0;--n1,--n) { int temp=(s1[n1]-'0')*(s2[n2]-'0'); cheng[n-1]=char(cheng[n-1]+(cheng[n]+temp-'0')/10); cheng[n]=char((cheng[n]+temp-'0')%10+'0'); } if(count(cheng)==cheng.length()) return "0"; return cheng.substr(cheng.find_first_not_of('0'));} string sum(string s1,string s2){ if(s1.length()<s2.length()) { string temp=s1; s1=s2; s2=temp; } for(int n1=s1.length()-1,n2=s2.length()-1;n1>=0;n1--,n2--) { s1[n1]=char(s1[n1]+(n2>=0?s2[n2]-'0':0)); if(s1[n1]-'0'>=10) { s1[n1]=char((s1[n1]-'0')%10+'0'); if(n1) s1[n1-1]++; else s1="1"+s1; } } return s1;} string change(int a){ string s1=""; char s2[10000]; int i=0; while(a) { s2[i++]=(a%10)+'0'; a/=10; } for(--i;i>=0;--i) s1+=s2[i]; return s1;} int main(){ //freopen("b.txt","w",stdout); string h[3],k[3],aa; long long lp[3],lq[3],a[3]; int n; while(scanf("%d",&n)!=EOF) { if((int)sqrt((double)n)*(int)sqrt((double)n)==n) { printf("no solution\n"); continue; } int s; a[2]=s=sqrt((double)n); h[0]="0";h[1]="1"; k[0]="1";k[1]="0"; lp[1]=0;lq[1]=1; int p=2; while(1) { if(p==0) { lp[0]=-lp[2]+a[0]*lq[2]; lq[0]=(n-lp[0]*lp[0])/lq[2]; a[1]=floor((double)(lp[0]+s)/lq[0]); h[0]=sum(muling(change(a[0]),h[2]),h[1]); k[0]=sum(muling(change(a[0]),k[2]),k[1]); } else if(p==1) { lp[1]=-lp[0]+a[1]*lq[0]; lq[1]=(n-lp[1]*lp[1])/lq[0]; a[2]=floor((double)(lp[1]+s)/lq[1]); h[1]=sum(muling(change(a[1]),h[0]),h[2]); k[1]=sum(muling(change(a[1]),k[0]),k[2]); } else { lp[2]=-lp[1]+a[2]*lq[1]; lq[2]=(n-lp[2]*lp[2])/lq[1]; a[0]=floor((double)(lp[2]+s)/lq[2]); h[2]=sum(muling(change(a[2]),h[1]),h[0]); k[2]=sum(muling(change(a[2]),k[1]),k[0]); } string s1=muling(h[p],h[p]); string s2=sum("1",muling(change(n),muling(k[p],k[p]))); if(s1==s2) //h[p]*h[p]==1+n*k[p]*k[p] { cout<<h[p]<<endl; break; } p++; p%=3; } } return 0;}
I题:1~n n个数排成一行,每次把偶数位置上的数抽出来,再把奇数位置上的一个一个接在后面,形成一个新数列,问M次操作之后,前X个数分别是什么。因为M很大,肯定不能暴力。
先假设这个数列无限大,那么M次操作之后,第一个数是2^m,第二个数是2*2^m,第三个数是3*2^m……………………
那么假如这个数列的个数是奇数的话,因为2^m和n互质,把每个数%n就能得到答案了。
那么如果这个数是偶数呢?很容易发现,如果数列是奇数的话,最后一个数永远都不会变,那么我们能把它看成一个n+1长度的数列,对n+1取模就行了。
加个快速幂,然后如果模出0的话记得变成n。
#include<set>#include<cmath>#include<stack>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cstdlib>#include<numeric>#include<vector>#include<ctime>#include<queue>#include<list>#include<map>#define pi acos(-1)#define INF 0x7fffffff#define clr(x) memset(x,0,sizeof(x));#define clrto(x,siz,y) for(int xx=0;xx<=siz;xx++) x[xx]=y;#define clrset(x,siz) for(int xx=0;xx<=siz;xx++) x[xx]=xx;#define clrvec(x,siz) for(int xx=0;x<=siz;xx++) x[xx].clear();#define fop freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#define myprogram By_135678942570#define clrcpy(x,siz,y) for(int xx=0;xx<siz;xx++) x[xx]=y[xx];using namespace std;main(){ int n,m,x; while(scanf("%d%d%d",&n,&m,&x)!=EOF) { if(n%2==0) n++; long long a=1; long long temp=2; while(m) { if(m&1) a*=temp,a%=n; temp*=temp,temp%=n; m>>=1; } int sum=0; for(int i=0;i<x;i++) { sum+=a; sum%=n; printf("%d%c",sum==0?n:sum,i==x-1?'\n':' '); } } return 0;}
终于完整的做完一次比赛了。。。
虽然貌似略水。。
Posted by 135678942570 blog.csdn.net/ttl_135678942570
- 2010 辽宁省省赛 题解
- 辽宁省赛2010
- 辽宁省赛2010
- 辽宁省赛2010 G
- Friends number 2010辽宁省赛
- 2014辽宁省省赛 luckly number
- 2010 ACM/ICPC 辽宁省赛 Dinner
- 【9018p1316】SPY(辽宁省赛2010)
- 辽宁省赛2010 G题 Friends Number
- 辽宁省赛2010-time[水题]
- 2010辽宁省赛You are my brother
- 2014辽宁省赛 Traveling
- 辽宁省赛总结
- 2010辽宁省赛 NBUT 1222 English Game【字典树+DP】
- 2012.6辽宁省赛 Problem F
- 2014辽宁省赛 Repeat Number
- 2014年辽宁省赛 distance
- 忆2015年辽宁省赛
- Uml 与 Rational Rose( 类图 )
- 黑马程序员之ADO.NET 学习笔记:多种ADO.NET属性
- MySql安装后启动不成功的原因
- DO-178C与 DO-178B区别
- Registry.First.Aid.Platinum.v8.3.0.2054.Multilingual.Incl.Keymaker-CORE
- 2010 辽宁省省赛 题解
- Oracle中BLOB和CLOB数据的读写
- 黑马程序员之JS学习笔记:简单的LINQ的查询语法和方法语法
- Android实现数据存储技术
- 黑马程序员__classpath配置和java注释
- Spring MVC Hello World Example
- 7 递归
- 与这10种人聊天终身受益
- 四数最大程序报告