A:传送门:https://ac.nowcoder.com/acm/contest/5203/A
将每个数的每一位数先开一个数组存起来,然后在合成新的一个数。比如:2374,我们先放在a数组,分别为a[0]=2,a[1]=3,a[2]=7,a[3]=4,然后就可以将它重新组成之前那个数的相反数了。这样做的好处是可以不用考虑前导0的情况。
#include<bits/stdc++.h> using namespace std; int a[10]; int main(){ int n; cin>>n; int k=0; int num=0; int t=n; //注意,先将n存放起来,因为等下会改变n while(n){ //将n的各个位数存在a数组 int temp=n%10; a[k++]=temp; n/=10; } for(int i=0;i<k;i++){ //重新组合成新的数 num=num*10+a[i]; } int ans=num+t; cout<<ans<<endl; return 0; }
B:传送门:https://ac.nowcoder.com/acm/contest/5203/B
题意:大概的意思是从n个数中选取若干个数,使得他们的和为3600的倍数,如果有,就输出“YES”,否则输出“NO”。
思路:对于这题,我们要进行一下几个优化:
1,首先,对于每个输入的数字都mod3600,以降低他们的大小,这是不会有什么影响的,反正都是找他的倍数。
2,我们可以想到,我们将讨论的范围已经缩小在了[0,3600)这个区间范围内了,我们要尽快的找到他们所有数的任意组合所组成的数在这个区间是否出现过,而我们最最希望找的是有0出现过。这样我们呢就找到了。我们将任意个数组合处理后的数都存入dp数组中,如果某一次我们找到了dp[0]!=0,那么我们呢就找到了。
3,先看代码最核心的地方:
for(int i=0;i<3600;i++){ //对0到3600之间的所有数字进行分析 if(dp[i]>0||i==0) temp[(i+a)%3600]=1; //i等于0的时候其实是存的a本身,其他的时候就是存的组合而成的数 //如果在之前出现过这个数,那么直接继续令它为1 } for(int i=0;i<3600;i++){ if(temp[i]==1){ dp[i]=1; temp[i]=0; } }
我们每输入一个数字,记为a,就在当前的情况下进行处理,我们从0-3600进行遍历,我们讨论这个区间内的每一个数,如果在这区间内的某个数字在之前已经出现过,那么我们将这个数加上a再mod3600存入temp数组,说明这他们组合而成的新的数字,我们先暂时将他们存入temp数组里面,在处理完这个新输入的数字对我dp区间的影响之后,我们就要将新加入的成员添加到dp数组里面了,说明他是存在的。这就要靠第二个for循环来实现,如果temp数组为1的话,说明它存在,然后将这个数字对应的dp置为1。但是这里要注意了,我们还要重新将temp中间数组置为0,不然再输入下一个数字之后我们又得重新存入之气那已经出现过的数字,当然,这只是优化,可有可无。
4,我们对输入的数字不用数组存,而是直接用a表示。
#include<bits/stdc++.h> using namespace std; int n; int dp[10000],temp[100010]; //dp[i]表示的是这个数是否出现过 void solve(){ cin>>n; memset(dp,0,sizeof(dp)); memset(temp,0,sizeof(temp)); for(int j=1;j<=n;j++){ int a; //为了优化,我们不用数组存储数值 cin>>a; a%=3600; if(!dp[0]){ //如果有求模后为0的情况,说明存在符合条件的情况 for(int i=0;i<3600;i++){ //对0到3600之间的所有数字进行分析 if(dp[i]>0||i==0) temp[(i+a)%3600]=1; //如果在之前出现过这个数,那么直接继续令它为1 } for(int i=0;i<3600;i++){ if(temp[i]==1){ dp[i]=1; temp[i]=0; } } } } if(dp[0]) cout<<"YES"<<endl; else cout<<"NO"<<endl; } int main(){ std::ios::sync_with_stdio(false); cin.tie(NULL); int t; cin>>t; while(t--){ solve(); } return 0; }
C:传送门:https://ac.nowcoder.com/acm/contest/5203/C
我们可以看到,对于l和r的范围是相当大的,所以我们要进行优化。在l,r中的完全平方数,完全可以向求出对l和r开方之后的数值。例如l=165,r=10004;我们可以看到,l开方后为12,r开方后为100,那么中间有多少个数就我们要求的答案了。
但是我们还要考虑一些特殊情况:
1,假如l是刚好是平方数呢,那么就还要多加1,比如,l=9,r=32,那么他们之间就有5-3+1个平方数。这里是要进行特判的。
2,还有就是假如输入的l,r在两个相邻的平方数之间,而且l恰好为平方数,比如:l=9,r=14,结果就是1。
这两种情况就是要进行特判的。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ int n; cin>>n; while(n--){ ll l,r; cin>>l>>r; int ans=0; double t1=sqrt(l),t2=sqrt(r); if(t1==t2&&t1!=(int)t1) ans=0; //进行特判第二种特殊情况 else{ int k1=t1,k2=t2; if(k1*k1!=l) k1=t1+1; //特判第一种情况 ans=(k2-k1+1); } cout<<ans<<endl; } return 0; }