第四届“图灵杯”NEUQ-ACM 程序设计竞赛(团队赛)
2017-10-20 23:11
471 查看
问题 A: 谷神的赌博游戏
题目描述NEUQ的谷神要和我赌一个游戏:谷神要求我随机在纸上写出整数集合{1,2,3,…,3n+1}(n是整数)的一个排列(即不重复的随机写出从1到3n+1的所有整数)。并且要求在我写的过程中,从我写的第一个数开始一直加到我正在写的数的总和不被3整除。如果我能写出来符合要求的一个排列,那么我就赢得游戏。那么问题来了,我赢得游戏的概率是多少?
输入
一组测试数据,第一行输入测试样例的数目k,接下来k行每行一个正整数n代表一个样例(1<=n<=15)。
输出
对于每个样例数据依次输出我赢得比赛的概率(结果保留小数点后9位有效数字)。
样例输入
1
1
样例输出
0.250000000
提示
例如n=1,则谷神要求我随机写1到4的排列,如果我按顺序写1 3 4 2则是合法的,因为1,1+3、1+3+4、1+3+4+2都不被3整除。如果我按顺序写1 2 3 4则是不合法的,因为当我写到2的时候1+2=3可以被3整除,不符合游戏规定。
这道题刚上来思路是对的,式子推半天没推出来,后来发现是0的位置的问题
因为要问加起来的这个数能不能被3整除,所以我们可以直接把所有数想成0,1,2,0一共有i个,1一共有i+1个,2一共有i个,所以问题放在了如何排列这道题上
我们先排1:一共有i!种
然后排2:因为最后的0不会影响最后的加法,所以你可以试一试2可以放在那些位置,最后发现只能摆成 1 1 2 1 2 1 2这种的形式,所以2一共有(i+1)!种
最后排0:刚开始0可以放到(2i+1)个地方(第一个位置不可以放!),然后第二个0可以放到(2i+2)个地方,一共有i个,所以一共可以放到3i个地方
所以最后的式子就变成了i!*(i+1)!*(2i+1)*(2i+2)…*3i/(3i+1)!
附上AC代码:
#include<bits/stdc++.h> using namespace std; using LL=int64_t; const int INF=0x3f3f3f3f; int main() { ios::sync_with_stdio(0); cin.tie(0); int T; cin>>T; for(int i=0;i<T;i++) { int temp; double sum=1; cin>>temp; for(int i=1;i<=temp;i++) sum*=(double)i; for(int i=temp+2;i<=temp*2;i++) sum/=(double)i; sum/=(double)(3*temp+1); cout<<fixed << setprecision(9) << sum<<endl; } return 0; }
问题 B: 一个简单的问题
题目描述实验班最近在准备购置新的书籍。现在统计出了一份有十本书的书单,但是由于预算有限,必须删掉一本书。大家讨论决定把价格第三高的书删掉,请你找出这本书。
输入
第一行是一个整数T(1<=T<=1000),表示有T组数据。接下来的T行,每行有十一个整数,第一个整数表示这是第几组输入数据,接下来的十个整数表示你要处理的十本书的价格。每组数据用空格分隔,书的价格不超过1000。
输出
对每组输入数据,输出它的组号和第三高的价格,用空格分隔。
样例输入
3
1 1 2 3 4 5 6 7 8 9 10
2 931 240 986 894 826 640 965 833 136 138
3 940 955 364 188 133 254 501 122 768 408
样例输出
1 8
2 931
3 768
AC代码:
#include<bits/stdc++.h> using namespace std; using LL=int64_t; const int INF=0x3f3f3f3f; int main() { ios::sync_with_stdio(0); cin.tie(0); int n,x; cin>>n; for(int i=1;i<=n;i++) { int ans[10]; cin>>x; for(int j=0;j<10;j++) cin>>ans[j]; sort(ans,ans+10); cout<<i<<" "<<ans[7]<<endl; } return 0; }
问题 C: 来简单地数个数
题目描述这是一个斐波那契数列:
f1 = 1
f2 = 2
fn = fn-1 + fn-2 (n>=3)
蔡老板想知道,给你两个数a、b,你能否求出在区间[a,b]里有多少个斐波那契数。
输入
多组数据输入。一行为一组输入数据,包括两个非负整数a、b(a <= b <= 10^100),当a=b=0时输入终止。
输出
对每组输入,输出单独一行,包含一个整数表示区间[a,b]里的斐波那契数个数。
样例输入
10 100
1234567890 9876543210
0 0
样例输出
5
4
这道题调试了好久,最后终于调出来了,就是判断a,b的时候a和b有一个可能为0,我想的方法是先把前1000个斐波那契写出来然后判断,写斐波那契确实费了一些时间,还有关于范围的确定也确实好费事
附上AC代码:
#include<bits/stdc++.h> using namespace std; using LL=int64_t; const int INF=0x3f3f3f3f; const int num=1005; int fib[num][105]; int temp[num][105]; int length[num]; void init() { memset(temp,0,sizeof(temp)); memset(fib,0,sizeof(fib)); temp[0][0]=fib[0][0]=1,temp[1][0]=fib[1][0]=1; length[0]=0;length[1]=0,length[2]=0; for(int i=2;i<num;i++) { for(int j=0;j<105;j++) { temp[i][j]+=temp[i-1][j]+temp[i-2][j]; if(temp[i][j]>=10) { temp[i][j]-=10; temp[i][j+1]++; } } for(int j=104;j>=0;j--) if(temp[i][j]>0) { length[i]=j; break; } for(int j=length[i];j>=0;j--) fib[i][length[i]-j]=temp[i][j]; } } bool compear1(string x,int n) { if(x.length()<length +1) return true; if(x.length()>length +1) return false; for(int i=0;i<x.length();i++) { if(fib [i]>x[i]-'0') return true; if(fib [i]<x[i]-'0') return false; } return true; } bool compear2(string x,int n) { if(x.length()>length +1) return true; if(x.length()<length +1) return false; for(int i=0;i<x.length();i++) { if(fib [i]<x[i]-'0') return true; if(fib [i]>x[i]-'0') return false; } return true; } int main() { init(); ios::sync_with_stdio(0); cin.tie(0); string a,b; while(cin>>a>>b) { if(a=="0"&&b=="0") break; int temp1=0,temp2=0; for(int i=1;i<num;i++) { if(compear1(a,i)) { temp1=i;break; } } for(int i=num-1;i>=1;i--) { if(compear2(b,i)) { temp2=i;break; } } cout<<temp2-temp1+1<<endl; } return 0; }
下面是标程:
/* 先算前480个fibs,然后二分确定a和b数列fibs里的位置,ab两位置求个差值,就可以得到他们中间包含的fibs个数。 a和b也是fibs的情况特判一下。 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 500 #define MAXLEN 110 #define LAST MAXLEN-2 char store[MAXN][MAXLEN]; char *Fibs[MAXN]; char* IntAddition(char *a,char *b,char *sum){ int i,j,k,first; for(i=strlen(a)-1,j=LAST;i>=0;i--,j--){ sum[j]=a[i]-'0'; } for(i=strlen(b)-1,k=LAST;i>=0;i--,k--){ sum[k]+=b[i]-'0'; } first=j<k?j:k; for(i=LAST;i>=first;i--){ sum[i-1]+=sum[i]/10; sum[i]=sum[i]%10+'0'; } while(sum[first]=='0'&&first<LAST){ first++; } return &sum[first]; } void Fibonacci(void){ memset(store,0,sizeof(store)); memset(Fibs,NULL,sizeof(Fibs)); strcpy(store[1],"1"); strcpy(store[2],"2"); Fibs[1]=store[1]; Fibs[2]=store[2]; int i; for(i=3;i<485;i++){ Fibs[i]=IntAddition(Fibs[i-2],Fibs[i-1],store[i]); } } int Compare(char *a,char *b){ int lenA=strlen(a); int lenB=strlen(b); if(lenA==lenB) return strcmp(a,b); return lenA>lenB?1:-1; } int BinarySearch(char *num,bool &flag){ int low=1; int high=480; while(low<=high){ int mid=(low+high)/2; int res=Compare(num,Fibs[mid]); if(res==0){ flag=true; return mid; } else if(res<0) high=mid-1; else low=mid+1; } return low; } int main(){ Fibonacci(); char a[MAXLEN],b[MAXLEN]; while(scanf("%s %s",a,b)!=EOF){ if(strcmp(a,"0")==0&&strcmp(b,"0")==0){ break; } bool flagLeft=false; bool flagRight=false; int left=BinarySearch(a,flagLeft); int right=BinarySearch(b,flagRight); if (flagRight) printf("%d\n",right-left+1); else printf("%d\n",right-left); } return 0; }
问题 D: 简单的图形输出
题目描述谢尔宾斯基三角形是一种分形,它的构造过程是这样的:
1.取一个实心的三角形。(多数使用等边三角形)
2.沿三边中点的连线,将它分成四个小三角形。
3.去掉中间的那一个小三角形。
4.对其余三个小三角形重复1。
我们想尝试用斜线、反斜线和下划线画出谢尔宾斯基三角,假设最小的三角是长这样的:
/\
/__\
具体规律详见样例。
输入
多组数据输入输出。每行有一个整数n(1<=n<=10),表示执行了一次操作1,n=0时结束输入。
输出
画出执行n次操作1后的图形,调整你的输出到最左端(底边的第一个斜杠在第一列)。输出不能包含任何尾随空格。在每个测试用例后打印空行。
样例输入
3
2
1
0
样例输出
/\
/__\
/\ /\
/\/\
/\ /\
/\ /\
/\ /\ /\ /\
/\/\/\/\
/\
/__\
/\ /\
/\/\
/\
/__\
递归题,标程代码:
//递归 #include <cstdio> #include <cstring> #define N 2050 using namespace std; int n; char s[N/2] ; void print(int x,int y,int d){ int offset=1<<(d-1); if(d==1){ s[x][y]=s[x+1][y-1]='/'; s[x][y+1]=s[x+1][y+2]='\\'; s[x+1][y]=s[x+1][y+1]='_'; return ; } print(x,y,d-1); print(x+offset, y-offset, d-1); print(x+offset, y+offset, d-1); } int main(){ while(scanf("%d",&n) && n){ int i,j,k; for(i=1;i<=(1<<n);i++) for(j=1;j<=(1<<(n+1));j++) s[i][j]=' '; print(1,(1<<n),n); k=(1<<n)+1; for(i=1;i<=(1<<n);i++,k++){ for(j=1;j<=k;j++) putchar(s[i][j]); printf("\n"); } printf("\n"); } return 0; }
问题 G: 那么大奶牛之神
题目描述那么大奶牛之神把一个神秘数字通过信使传递给了奶牛们,但由于信件上出现了偏差,一个数字变成了两个数字,现在你需要通过这两个数字还原出大么大奶牛之神给的神秘数字。需要用第二个数字通过加(+),减(-),乘(*),除(/),次幂(^),阶乘(!),开平方(√)这几个符号凑出第一个数字。使用第二个数字的次数最少的时候,那么使用次数就是神秘数字。
例如第一个数字是300,第二个数字是7,那么7用得最少是6次,所以神秘数字是6。具体方法如图用了6个7。虽然最优解的算式不是唯一的,但是并不妨碍得到最少的使用次数。
现在得知第一个数字是51,第二个数字是整数n(0< n< 10),求神秘数字。
输入
输入n(0< n<10)
输出
输出神秘数字
样例输入
1
样例输出
8
传说中的真正防AK题,出奇的脑洞,官方题解是找规律…..
51#1最优解1+(111-11)/(1+1)
51#2最优解2+2/2+2*(2*2)!
51#3最优解3!*3+33
51#4最优解4!*(√4+√√√(√4^(-4!)))
51#5最优解5/5+55-5
51#6最优解(6!-6*6)/(6+6)-6
51#7最优解7*7+(7+7)/7
51#8最优解√√(8+8)+√(√(8-8/8)^8)
51#9最优解(√9)!*9-√9
51的9个最优解是864456563
标程:
#include<iostream> using namespace std; int main() { int n,a[10]={0,8,6,4,4,5,6,5,6,3}; while (cin >> n){ cout << a << endl; } return 0; }
问题 I: 一道不简单的题目
题目描述这是一道拼手速的题!
你在跟acmclub机器人对话。对它说:“Is this NEUQ?”,它会回答你:“Yes, welcome to NEUQ.”。对它说:“I have some question!”,它会回复:“What can I do for you?”。
输入
输入为一句话。
输出
输出也为一句话。
样例输入
Is this NEUQ?
样例输出
Yes, welcome to NEUQ.
注意第一句Is this NEUQ?的问号是中文问号
AC代码:
#include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); string q; getline(cin,q); if(q=="Is this NEUQ£¿") cout<<"Yes, welcome to NEUQ."<<endl; if(q=="I have some question!") cout<<"What can I do for you?"<<endl; return 0; }
问题 J: 简单的变位词
题目描述变位词是指改变某个词的字母顺序后构成的新词。蔡老板最近沉迷研究变位词并给你扔了一道题:
给你一些单词,让你把里面的变位词分组找出来。互为变位词的归为一组,最后输出含有变位词最多的前五组。如果有组数相同的按照字典序输出。
输入
输入包含由小写字母组成的单词,用换行分割,被EOF终止。 输入数据不超过30000个单词。
输出
输出五组包含单词数量最多的变位词,如果少于五组,输出全部。对每组输出,写出它的大小和成员词,成员词按字典序排序用空格分隔,每组输出之间用换行分隔,相同词只输出一次,但算个数。
样例输入
neuq
tea
bate
beat
caret
trace
nueq
carte
cater
crate
abet
ate
eat
beta
eta
signal
样例输出
Group of size 5: caret carte cater crate trace .
Group of size 4: abet bate beat beta .
Group of size 4: ate eat eta tea .
Group of size 2: neuq nueq .
Group of size 1: signal .
这道题写了一中午+半下午,其实最主要的就是要灵活运用STL中的各种容器,这道题我的思路就是首先一个map< key,value>第一个key是按字典序排好的,第二个是一个set用来储存字典序相同的string,然后再用一个map< key,value>用来保存按字典序排好的string对应的数量,然后找到数量最多的,如果数量相同,就在比较字典序最后输出
附上AC代码:
#include<bits/stdc++.h> using namespace std; map<string,set<string> >ans; map<string,int>cnt; map<string,int>::iterator is; set<string>::iterator its; int main() { string x; while(cin>>x) { string temps=x; sort(x.begin(),x.end()); ans[x].insert(temps); cnt[x]++; } string max_temp; int time=0; while(time<5&&ans.size()) { int maxn=0; for(is=cnt.begin();is!=cnt.end();is++) { if(is->second > maxn) {maxn=is->second;max_temp=is->first;} else if(is->second==maxn) { if(*ans[is->first].begin()<*ans[max_temp].begin()) max_temp=is->first; } } cout<<"Group of size "<<maxn<<": "; for(its=ans[max_temp].begin();its!=ans[max_temp].end();its++) { cout<<*its<<" "; } cout<<"."<<endl; time++; ans.erase(max_temp); cnt.erase(max_temp); } return 0; }
下面附上标程:
/* 所有字符串统计字符后hash,排完序就确定每组的个数、确定一组中字典序最小的字符串。 再根据个数以和字符串对组进行排序。 */ #include<cstdio> #include<cstring> #include<vector> #include<map> #include<algorithm> using namespace std; const int maxn=30005; const int maxm=30; const int X=30; typedef unsigned long long ll; typedef pair<ll,int> pii; int N,M,E; vector<pii> vec,grop; vector<int> g[maxn]; char word[maxn][maxm],st[maxn][maxm]; inline ll Hash(char* s){ int len=strlen(s),c[maxm]; memset(c,0,sizeof(c)); for(int i=0;i<len;i++) c[s[i]-'a']++; ll ret=0; for(int i=0;i<26;i++) ret=ret*X+c[i]; return ret; } inline bool cmp (const pii& a,const pii& b){ if(a.second==b.second) return strcmp(st[a.first],st[b.first])<0; return a.second>b.second; } inline bool sort_by(const int& a,const int& b){ return strcmp(word[a],word[b])<0; } int main(){ N=M=E=0; vec.clear(); grop.clear(); while(scanf("%s",word )==1){ ll key=Hash(word ); vec.push_back(make_pair(key,N)); N++; } sort(vec.begin(),vec.end()); int cnt=0; ll pre=-1; for(int i=0;i<vec.size();i++){ int idx=vec[i].second; if(vec[i].first!=pre){ if(cnt) grop.push_back(make_pair(M++,cnt)); cnt=0; g[M].clear(); pre=vec[i].first; strcpy(st[M],word[idx]); } cnt++; g[M].push_back(idx); if (strcmp(word[idx],st[M])<0) strcpy(st[M],word[idx]); } if (cnt) grop.push_back(make_pair(M++,cnt)); sort(grop.begin(),grop.end(),cmp); for(int i=0;i<min(5,(int)grop.size());i++){ printf("Group of size %d: ",grop[i].second); int x=grop[i].first; sort(g[x].begin(),g[x].end(),sort_by); for (int j=0;j<g[x].size();j++){ if (j==0||strcmp(word[g[x][j-1]],word[g[x][j]])) printf("%s ",word[g[x][j]]); } printf(".\n"); } return 0; }
相关文章推荐
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-F-一道简单的递推题
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-G-那么大奶牛之神
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-C-来简单地数个数
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-D-简单图形输出
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-J-简单的变位词
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-E-简单的RMQ
- 图灵杯-第四届“图灵杯”NEUQ-ACM 程序设计竞赛-A-谷神的赌博游戏
- 山东省第四届ACM大学生程序设计竞赛 A^X mod P
- 山东省第四届ACM大学生程序设计竞赛 The number of steps(概率dp&全期望)
- 2013年山东省第四届ACM大学生程序设计竞赛-最后一道大水题:Contest Print Server
- 2013年山东省第四届ACM大学生程序设计竞赛:Rescue The Princess
- [2013山东省第四届ACM大学生程序设计竞赛]——Contest Print Server
- 山东省第四届ACM大学生程序设计竞赛 Rescue The Princess
- 第四届“图灵杯”NEUQ-ACM程序设计竞赛部分题解
- 2013年山东省第四届ACM大学生程序设计竞赛 Problem A Rescue The Princess 向量法 水题
- Alice and Bob(山东省第四届ACM大学生程序设计竞赛 )
- 第四届“图灵杯”NEUQ-ACM程序设计竞赛(团队赛)-网络同步赛D 分形
- 2013年山东省第四届ACM大学生程序设计竞赛 Problem I Thrall’s Dream 图,2n遍dfs
- A^X mod P(山东省第四届ACM大学生程序设计竞赛 )
- Rescue The Princess(山东省第四届ACM大学生程序设计竞赛 )