ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

暑假周测题解2

暑假周测题解2

1.乐谱

题目:

农夫约翰打算教他的奶牛如何唱歌。歌曲包含\(N(1<=N<=100)\)个节拍,第 i 个节拍持续\(B_i(1<=B_i<=100)\)个音符。奶牛从第0时间开始唱歌,她们从第 0至\(B_1-1\)个时间唱第1个节拍,从第\(B_1\)\(B_1+B_2-1\)唱第2个节拍,依此类推。
奶牛们对唱歌已经失去了兴趣,因为他们觉得这首歌既长又无聊。因此,为了提高奶牛们的注意力,农夫约翰设计了一份\(Q(1<=Q<=1000)\)个问题的问卷,"从节拍T到节拍T+1之间,你知道演奏的是哪一个音符么?" 奶牛们非常需要你的帮助,不然她们就回答不了这些问题了。问题中\(T_i(0<=T_i<=10000)\)完全符合范围。

分析:

签到题,算一下前缀和,每次判断一下即可。

程序:

#include<bits/stdc++.h>
using namespace std;
int n,q,a[101],b[1001],f[101];
int main()
{cin>>n>>q;for(int i=1;i<=n;i++){cin>>a[i];f[i]=f[i-1]+a[i];}for(int i=1;i<=q;i++)cin>>b[i];for(int i=1;i<=q;i++)for(int j=1;j<=n;j++)if(b[i]<f[j]){cout<<j<<'\n';break;}return 0;
}

2.起伏数

题目:

起伏数是在一对数字之间交替转换的数,如1212121,双重起伏数则是指在两种进制下都是起伏数的数,如十进制数191919是一个十进制下的起伏数,它对应的十一进制数121212也是一个起伏数,所以十进制数191919是一个双重起伏数。
类似的可以定义三重起伏数,三重起伏数在三种不同的进制中都是起伏数,甚至还有四重起伏数,如十进制300=606(七进制)=363(九进制)=454(八进制)=1A1(十三进制)…,你的任务就是在指定范围内找出双重、三重、四重起伏数。

题目条件:

1.输入条件:单独一行包含五个用空格隔开的十进制整数,前两个数表示进制的范围(2到32),第三与第四个数表示指定的范围(1到10000000),第五个数为2,3,4中的一个,表示要找的起伏数的重数。
2.输出条件:从小到大以十进制形式输出指定范围内的指定重数的起伏数。一行输出一个数。

分析:

暴力的方法就是直接枚举区间内的每一个数,接着枚举进制,把这个数的起伏数重数算出来即可,注意这里位数至少为3位,而且起伏数中的这一对数字不能是一样的。接下来我们换一个枚举的思路,一开始我们枚举每个数,现在我们可以先枚举进制,接着生成这个进制的起伏数,枚举进制,枚举第一个数,枚举第二个数,枚举位数,接着将这个数转化为十进制判断,很明显比刚才枚举一千万个数时间复杂度更优秀。这里有可能生成出重复的数,因此最好记录下来再判断。

程序:

#include<bits/stdc++.h>
using namespace std;
int l,r,p,q,m,a[51],ans[10001],s;
int zs(long long x,long long y,int s,int k)
{int sum=0;for(int i=s-1;i>=0;i--){if((s-i)%2==1)sum+=x*pow(k,i);elsesum+=y*pow(k,i);if(sum>q)return -1;}if(sum>=p)return sum;return -1;
}
bool check(int n,int x)
{int s=0,v=n;while(v){a[++s]=v%x;v=v/x;}if(s<=2)return 0;for(int i=s;i>=3;i--)if(a[i]!=a[i-2]||a[i]==a[i-1])return 0;return 1;
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cin>>l>>r>>p>>q>>m;for(int k=l;k<=r;k++){for(int i=1;i<k;i++)for(int j=0;j<k;j++)if(i!=j){for(int h=1;h<=25;h++){int v=zs(i,j,h,k);if(v==-1)continue;int t=0;for(int g=l;g<=r;g++)t+=check(v,g);if(t==m)ans[++s]=v;}}}sort(ans+1,ans+s+1);for(int i=1;i<=s;i++)if(ans[i]!=ans[i-1])cout<<ans[i]<<'\n';return 0;
}

3.幸运数字

题目:

数字4和7是幸运数字,而其他的都不是幸运数字。一个整数是幸运数字,当且仅当它的十进制表示只包含幸运数字。现在让你给出第K大的幸运数字。

题目条件:

第一行一个整数\(K(1<=K<=1000000000)\),30%的数据,K不超过100万。

分析:

我们可以一位位来构造这个第K大的幸运数字,然后先算出K的位数,如果K大于2就说明K至少是两位数,接着减去二,与22比较,以此类推,这样先求出k的位数,然后枚举每一位,从高位开始比较,如果现在是第i位,K比2i-1大,那就是7,否则就是4。

程序:

#include<bits/stdc++.h>
using namespace std;
int k,i=1;
int main()
{ios::sync_with_stdio(false);cin.tie(0);cin>>k;while(k){if(k>pow(2,i)){k-=pow(2,i);i++;}elsebreak;}while(i>0){if(k>pow(2,i-1)){cout<<7;k-=pow(2,i-1);}elsecout<<4;i--;}return 0;
}

4.电缆公司的烦恼

题目:

某地的居民决定举办一场程序比赛。评委会保证要组织一次最公正的比赛。它将选手的电脑以"星"形的结构连接并连到一个中心计算机。组织者决定将所有电脑以同样的距离连到该中心计算机上。组织者要求电缆公司提供一定量的等长的电缆,并希望电缆越长越好从而使选手之间的距离尽可能远。电缆公司的老板知道他的电缆长度精确到厘米,而且他能以厘米为单位切割电缆。但是这次他不知道所需的电缆的长度。郁闷的老板找到你,希望你能提供一个程序可以算出为达到所需求数量,这些电缆最多能被切成多长。

题目条件:

第一行N,K表示公司里的电缆数和所需的电缆数。n<=100000,k<=600000接下来N行为每根电缆的长度(1米到100千米之间),精确到厘米(小数点后2位)。

分析:

显然,题目的答案是有单调性的,可以二分,第一如果用小数来二分的话精度很难控制,因此我们可以把他变成整数进行二分,会减少很多麻烦。

程序:

#include<bits/stdc++.h>
using namespace std;
long long n,k,a[100001];
bool check(long long x)
{long long sum=0;for(int i=1;i<=n;i++)sum+=a[i]/x;if(sum>=k)return 1;return 0;
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cin>>n>>k;for(int i=1;i<=n;i++){double x;cin>>x;a[i]=x*100;}long long l=0,r=1e8;while(l<r){long long mid=(l+r+1)/2;if(check(mid))l=mid;elser=mid-1;}cout<<fixed<<setprecision(2)<<l/100.0<<'\n';return 0;
}
返回列表