题解:
考察点: 数学,打表找规律
易错点:
注意最好把和都开成long long类型,因为在计算的过程中有可能会爆
解法:打表找规律
这题第一眼看上去并没有什么神奇的数学结论可以一眼秒掉,但数据范围又这门大,很显然可以通过打表来找规律。于是对以内的小数据进行暴力
#include "bits/stdc++.h" using namespace std; int main() { for(int i=1;i<=100;i++){ int sum=0; for(int j=1;j<=i;j++){ sum+=i/j; } if(sum%2==0){ if(i%100==0) printf("%d\n",i); else printf("%d ",i); } } printf("\n"); return 0; }
整理结果后有如下结果
4 5 6 7 8 16 17 18 19 20 21 22 23 24 36 37 38 39 40 41 42 43 44 45 46 47 48 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 100
很显然可以从上表中观察出来,当为偶数时,位于区间内数全为满足要求的怪数。
有了这个结论之后,对于整数,就可以快速统计出内的怪数个数。设,则对进行分类讨论。如果是奇数,则说明从一直到之后不可能再存在怪数。而前面的怪数个数。而如果是偶数,则说明后面从到还存在怪数,故结果应该是最后还应该加上。最后的集过应该为区间内的个数,减去区间内的个数。
#include "bits/stdc++.h" using namespace std; typedef long long LL; LL a,b; LL solve(LL x){ if(x<0) return 0; if(x==0) return 1; LL v=sqrt(x),s=0; if(v%2){ return v*(v+1)/2; }else{ LL t=v-1; s=t*(t+1)/2; s+=x-v*v+1; } return s; } int main() { scanf("%lld%lld",&a,&b); printf("%lld\n",solve(b)-solve(a-1)); return 0; }