【有奖】NOIP普及组模拟赛 个人邀请赛 乐多赛
题目描述
日本数学家角谷有一个猜想:任意一个自然数,经过以下过程,最终会得到1。现在请你打印出任意一个数使用角谷猜想转换为1需要几次。
演变方式:
1.如果这个数为奇数,则将它×3+1。如果这个数为偶数,则将它÷2。
2.当这个数为1时,结束计算。
输入输出格式
输入格式:
输入共1行。
第1行:a,代表演变前的数。
输出格式:
一个自然数n,表示需要n次才能用角谷猜想把这个数变成1
输入输出样例
输入样例#1:
8
输出样例#1:
3
说明
数据可能很大,要用高精度
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define N 200500 int num[N]={1}; int n,m,len=1; char s[N]; unsigned long long tot=0; void mul(int k){ for(int i=1;i<=len;i++){ num[i]*=k; if(i>1){ num[i]+=num[i-1]/10; num[i-1]%=10; } } for(;num[len]>=10;len++){ num[len+1]=num[len]/10; num[len]%=10; } } void div(int k){ int d=0; for(int i=len;i;i--){ d=d*10+num[i]; num[i]=d/k; d%=k; } while(!num[len]) len--; } void add1(){ int t=1; num[1]+=1; while(num[t]>9) num[t+1]+=num[t]/10,num[t]%=10,t++; if(t>len) len=t; } bool judge(){ if(len==1&&num[1]==1) return 1; return 0; } bool odd(){ return num[1]&1; } void dfs(){ if(judge()) return ; if(odd()) mul(3),add1(); else div(2); tot++; dfs(); } int main(){ cin>>s; int p=0; len=strlen(s); for(int i=len-1;i>=0;i--) num[++p]=s[i]-'0'; dfs(); cout<<tot; return 0; }
题目描述
有一个四则运算的表达式(+、-、*、/),它可能有一些多余的括号可以去掉。把这些括号去掉的条件是:可以改变运算顺序,只要表达式计算结果不变即可(每去掉一组括号都不能使结果变化)。现在请你输出去掉多余括号的表达式。
输入输出格式
输入格式:
一个表达式
输出格式:
去掉所有多余括号的表达式
输入输出样例
输入样例#1:
a+(b-c)
输出样例#1:
a+b-c
输入样例#2:
1+2*3
输出样例#2:
1+2*3
说明
数据保证所有的括号合法,表达式长度不超过100个字符
#include<string> #include<iostream> using namespace std; inline bool isOperator(char c){ return c=='+'||c=='-'||c=='*'||c=='/'; } bool allMulOrDiv(const string& exp){ for(int i=0,len=exp.size();i<len;++i){ if(exp[i]=='('){ int cnt=1; for(++i;true;++i){ if(exp[i]=='(') ++cnt; else if(exp[i]==')'){ --cnt; if(!cnt) break; } } ++i; } if(exp[i]=='+'||exp[i]=='-') return false; } return true; } int findMatchedLeft(const string& exp,int r){ int countOfRight=1; for(--r;r>=0;--r){ if(exp[r]==')') ++countOfRight; else if(exp[r]=='('){ --countOfRight; if(!countOfRight) break; } } return r; } string& simplify(string& exp){ int left,right=0; char head,tail,can; while((right=exp.find(')',right))!=string::npos){ left=findMatchedLeft(exp,right); //get info if(left&&isOperator(exp[left-1])) head=exp[left-1]; else head='+'; if(right+1<exp.size()&&isOperator(exp[right+1])) tail=exp[right+1]; else tail='+'; //analyze if(right-left==2) can=1; else if(head=='/') can=0; else if(head=='*'||head=='-') can=allMulOrDiv(exp.substr(left+1,right-left-1)); else can=tail=='+'||tail=='-'||allMulOrDiv(exp.substr(left+1,right-left-1)); //process if(can){ exp.erase(left,1).erase(right-1,1); --right; } else ++right; } return exp; } int main(){ string exp; getline(cin,exp); cout<<simplify(exp); return 0; }
题目描述
小偷的背包问题,大家知道是0-1背包问题。只是每件将要偷的物品的重量和价值都是带有1位小数的实数。小偷的背包可以装入物品的最大重量也是带有1位小数。
输入输出格式
输入格式:
两个数m (小偷背包的承重)和 n(物品件数) (1.0<=m<=100.0, 1<=n<=20)
以下是n行是每件物品的重量和价值。
输出格式:
最大价值。(带有1位小数,如果是整数,请输出 XXX.0)
输入输出样例
输入样例#1:
34.5 3 12.4 21.5 15.3 18.4 20.2 10.2
输出样例#1:
39.9
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int N=1e4+10; int n; double m,v[N],c[N],f[N]; int main(){ scanf("%lf%d",&m,&n); int V=m*10; for(int i=1;i<=n;i++) scanf("%lf%lf",&v[i],&c[i]),v[i]*=10,c[i]*=10; for(int i=1;i<=n;i++){ for(int j=V;j>=v[i];j--){ f[j]=max(f[j],f[j-(int)v[i]]+c[i]); } } f[V]/=10; printf("%.1lf",f[V]); return 0; }
题目描述
由n个节点可组成多少个不同的二叉树?
输入输出格式
输入格式:
一个正整数n。
输出格式:
不同的二叉树的个数。
输入输出样例
输入样例#1:
1
输出样例#1:
1
说明
测试数据规模:
保证40%的数据n<=35;
保证100%的数据n<=5000。
保证120%的数据n<=10000。
#include<cstdio> #include<cmath> int a[5005][5005],b[5005],n; void catalan() { int i,j,len,digit,t; a[1][0]=b[1]=len=1; for(i=2;i<=n;i++) { for(j=0;j<len;j++) a[i][j]=a[i-1][j]*(4*(i-1)+2); digit=0; for(int j=0;j<len;j++){ t=a[i][j]+digit; a[i][j]=t%10; digit=t/10; } while(digit){ a[i][len++]=digit%10; digit/=10; } digit=0; for(int j=len-1;j>=0;j--){ t=digit*10+a[i][j]; a[i][j]=t/(i+1); digit=t%(i+1); } while(!a[i][len-1])len--; b[i]=len; } } int main(){ scanf("%d",&n); catalan(); for(int i=b[n]-1;i>=0;i--) printf("%d",a[n][i]); return 0; }
更正AC代码:
#include<cstdio> using namespace std; const int N=1e6+10; int n,len; int f[N]; void mul(int x){ for(int i=1;i<=len;i++) f[i]*=x; for(int i=1;i<=len;i++){ f[i+1]+=f[i]/10; f[i]=f[i]%10; } while(f[len+1]){ f[len+2]=f[len+1]/10; f[len+1]%=10; len++; } } void div(int x){ for(int i=len;i>=1;i--){ f[i-1]+=f[i]%x*10; f[i]/=x; } for(int i=len;i>=1;i--)if(f[i]){len=i;break;} } int main(){ scanf("%d",&n); f[len=1]=1; for(int i=1;i<=n;i++)mul(4*i-2),div(i+1); for(int i=len;i;i--) printf("%d",f[i]); return 0; }