牛客算法周周练2
A. 相反数
签到题。
直接将原数分解后,重组即可。
#include<bits/stdc++.h> using namespace std; int n,b; void solve(int x){ while(x){ b=b*10+x%10; x/=10; } } int main(){ scanf("%d",&n); solve(n); printf("%d",b+n); return 0; }
B. Music Problem
题目大意:
判断一个序列里是否有子序列的和能够被整除。
对于这种序列的题目, 八成都是可以做的。
表示是否拥有在模意义下和为的子序列。
表示讨论到当前情况是否拥有在模下和为的子序列。也可以理解成 是 的上一版本
所以就有
#include<bits/stdc++.h> using namespace std; const int MAX_N=1e5+5; const int MAX_V=4000 + 5; int t,n,a[MAX_N]; bool f[MAX_V],temp[MAX_V]; int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); memset(f,0,sizeof(f)); memset(temp,0,sizeof(temp)); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a[i]%=3600; } for(int i=1;i<=n;i++){ if(f[0]) break; f[a[i]]=1; for(int j=1;j<3600;j++){ if(temp[j]) f[(a[i]+j)%3600]=1; if(f[0]) break; } /*也可以写成 for(int j=0;j<3600;j++) temp[j]=(f[j] || temp[j]) ? 1 : 0; 或者 for(int j=0;j<3600;j++) temp[j]=f[j]>temp[j]?f[j]:temp[j]; */ for(int j=0;j<3600;j++) temp[j]=f[j]; } printf((f[0]?"YES\n":"NO\n")); } return 0; }
C. 完全平方数
这道题根据题意,再观察一下样例,发现中最多有个完全平方数,但观察数据范围,可以为0,所以最多有个完全平方数,于是我们可以打一个暴力出来,时间复杂度
#include<bits/stdc++.h> using namespace std; int n; long long l,r; int main(){ scanf("%d",&n); while(n--){ int ans=0; scanf("%lld%lld",&l,&r); for(int i=(int)sqrt(l);i<=31622;i++){ if(i*i>=l && i*i<=r) ans++; if(i*i>r) break; } printf("%d\n",ans); } return 0; }
现在,就是想办法优化暴力,使其变成正解。
我们可以先预处理出中的所有的完全平方数个。
因为单调,所以可以二分查找出第一个大于等于 的完全平方数,二分查找出第一个大于的完全平方数,在将其下标相减,即可得到答案。
时间复杂度
#include<bits/stdc++.h> using namespace std; int n; long long l,r,a[32005]; int main(){ scanf("%d",&n); for(int i=0;i<=31622;i++) a[i]=i*i; while(n--){ scanf("%lld%lld",&l,&r); int L=lower_bound(a,a+31623,l)-a; int R=upper_bound(a,a+31623,r)-a; printf("%d\n",R-L); } return 0; }