总算是把题目全部都做出来了,但是最后系统判分的时候却傻眼了,三个题都没有AC,要么有些数据点runtime errror,要么直接就wrong answer,实在是令人揪心啊!最后复盘的时候才发现确实是出了一点纰漏,但是明明可以避免的了,我却全中招了,不得不令我反思啊!A题是漏掉了一个判断条件,在设计数据的时候也没有发现这个漏洞,就这样wrong answer了,B题有些数据点出现了runtime error,但是后来在VJ上补题的时候一样的代码最后还都AC了。C题是直接wrong answer了,后来发现也是欠考虑了。
A-
思路分析:
读题我们发现这道题的思路并不难,要求能够加或减一个数K或不操作得到一个相等的数列,我们不难发现,当这个序列不同的元素小于等于二的时候是一定能够实现的,不同元素为三的时候要求这三个数形成一个等差数列,除了上述情况,其他情况都是不可能满足题意的。
源代码如下:
#include<iostream> #include<algorithm> using namespace std; int t; int n; long long a[10]; int m; bool check(long long temp){ for(int i=0;i<m;i++){ if(temp==a[i]){ return false; } } return true; } int main(){ scanf("%d",&t); for(int ii=0;ii<t;ii++){ scanf("%d",&n); m=0; if(n<=2){ long long temp; for(int i=0;i<n;i++){ scanf("%lld",&temp); } cout<<"YES"<<endl; continue; }else{ m=0; scanf("%lld",&a[m]); m++; long long temp; for(int i=1;i<n;i++){ scanf("%lld",&temp); if(m<=5){ if(check(temp)){ a[m]=temp; m++; } } } if(m>=4){ cout<<"NO"<<endl; continue; }else{ if(m<=2){ cout<<"YES"<<endl; continue; } sort(a,a+m); if(2*a[1]==a[0]+a[2]){ cout<<"YES"<<endl; continue; }else{ cout<<"NO"<<endl; continue; } } } } }
B-
思路分析:
这道题使用可以使用尺取法来解决。按照题意,我们需要先从头读取26长度的字符串,然后不断调整这个head和tail,使其满足题设,然后输出第一个满足要求的并且字典序最小的答案。以下代码使用了数组a[26]来记录对应的每个字母的个数,m记录在这个长度内的'?'的个数。check()函数判断是否满足要求。首先使用一个初始化函数来先读取开始的26个字母,然后每次head++、tail++,并调整数组a,每次check一遍,符合要求则输出,程序结束。
以下是源代码:
#include<iostream> #include<string> #include<cstring> using namespace std; int a[26];// 0 or 1 string str; int m;//num of ? int n[26]; int lack;// currenet str lack num int head,tail; bool check(){ lack=0; for(int i=0;i<26;i++){ if(a[i]==0){ n[lack]=i; lack++; } } return lack==m; } void init(){ m=0; head=0;tail=26; lack=0; for(int i=0;i<26;i++){ if(str[i]=='?'){ m++; }else{ a[str[i]-'A']++; } } } void fuc1(){//head++ if(str[head]=='?'){ m--; }else{ a[str[head]-'A']--; } head++; } void fuc2(){//tail++ if(str[tail]=='?'){ m++; }else{ a[str[tail]-'A']++; } tail++; } void output(){ int tem=0; for(int i=0;i<26;i++){ if(str[head+i]=='?'){ cout<<(char)('A'+n[tem]); tem++; }else{ cout<<str[head+i]; } } cout<<endl; } int main(){ cin>>str; if(str.size()<26){ cout<<-1<<endl; return 0; } init(); while(tail<=str.size()){ if(check()){ output(); return 0; } // for(int i=0;i<26;i++){ // cout<<a[i]; // } // cout<<endl; fuc1(); fuc2(); } // cout<<"at the end"<<endl; cout<<-1<<endl; return 0; }
C-
思路分析:
首先我们将序列分为n个区间,每个区间是由1-n组成的序列,总体的思路就是先确定第q项在哪一个区间,然后再确定区间内的位置。
通过观察可以看出来,在1-9的时候,每个区间长度形成一个d=1的一个等差数列,10-99时,由于出现了两位数,区间仍形成一个等差数列,但是公差d++了,以此类推,由此我们可以知道区间长度是多个等差数列构成的。我们要到到这样的目的,给出区间数,然后求出这个区间的前面的总位数(包括自己),其实是将每个区间长度看为数列的项,求前向和Sn。根据数学知识我们可以得到计算公式。在每一个等差数列中Sn=n*a1+(n*(n-1)*d)/2, An=a1+(n-1)*d 。分别算出来不同区段的长度累加便可以得到第i个区间的前向和Sn。解决了这个问题剩下来就好解决了。我们可以通过二分的办法来确定第q项在哪个区间内,然后得到区间内的项数,再次使用二分的方法确定其在区间内的位置即可求出题解。
以下为源代码:
#include<iostream> #include<cstring> #include<string> #include<cmath> #define ll long long using namespace std; ll Sn(ll a1,ll n,ll d){ return n*a1+(n*(n-1)*d)/2; } ll An(ll a1,ll n,ll d){ return a1+(n-1)*d; } //计算第x个区间的前向区间位数和sum 包括x (利用多个等差数列的性质) ll fuc1(ll x){ ll tem=x; ll temp,cnt,a1,d,sum,n,alast,dlast; temp=10;cnt=0;a1=1;sum=0;d=1;dlast=1;alast=0; //Sn = n*a1+n*(n-1)/2 * d while(temp<=x){ n=temp-cnt-1; sum+=Sn(a1,n,d); alast=a1;dlast=d; a1=An(a1,n,d)+d+1; d++;temp*=10;cnt+=n; } temp/=10; n=x-temp+1; // d=dlast;a1=alast; sum+=Sn(a1,n,d); return sum; } ll fuc2(ll x) { ll temp=x; ll sum=0,n=0,d=0,cnt=1,dlast=1,alast=0; while(temp>=10){ cnt*=10; d++; n=cnt-cnt/10; sum=sum+n*d; temp/=10; } d++; n=x-cnt+1; sum=sum+n*d; return sum; } int main(){ ll n; cin>>n; for(ll i=0;i<n;i++){ ll q; cin>>q; ll left,right,mid; left=0;right=1e9;mid=(left+right)/2; ll ans=0; while(left<=right){ ll temp=fuc1(mid); if(temp<q){ ans=mid; left=mid+1; mid=(left+right)/2; }else{ // ans=mid; right=mid-1; mid=(left+right)/2; } } ll sum=fuc1(ans); q=q-sum; left=0,right=ans+1,ans=0; while(left<=right){ mid=(left+right)/2; ll sum=fuc2(mid); if(sum<q) { ans=mid; left=mid+1; } else { right=mid-1; } } sum=fuc2(ans); q-=sum; ans++; string str=to_string(ans); printf("%c ",str[q-1]); //cout<<str[q-1]<<endl; } //for(int i=0;i<10;i++){ // ll q; // cin>>q; // ll left,right,mid; // left=0;right=q;mid=(left+right)/2; // ll ans=fuc1(q); // cout<<ans<<endl; // } }