题目来源: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国的间谍有哪些E题:给一个图,图上的每条边都被一个人管理着,每条边有个过路费,第一次经过a管理的路时,只用交过路费,第二次要多交e[a],第三次要多交f[a]。问0~n-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; 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; }
正解应该是状态压缩搜索吧。因为管理者最多有9个,所以我们可以用一个3^9的数代表被管理的道路的状态。dp[i][j]代表到第i个点,状态为j,最少花费为多少,直接记忆化搜索一发应该就行了。。
比赛的时候直接爆搜过了,当时没多想就觉得数据很小有可能爆过去。。
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 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; }//爆搜的。。状压的看我心情写不写了。。。
#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