1. a-b<=a xor b,
对于在同一个数位相同的二进制位值,xor和减法的效果都是一样的。
对于在同一个数位不同的二进制位值,xor恒等于1,而减法可能向高位借1.
2.gcd(a,b)<=a-b (假设a>b)
因为gcd(a,b)=gcd(b,a%b)
设a=qb+r r=a%b=a-qb
gcd(b,a%b)=gcd(b,a-qb)
此时最大公因数不会超过a-qb
而a-qb<=a-b
所以gcd(a,b)=gcd(b,a%b)<=a-b
——————心累的分割线——————很明显吗——————
完整的思路总结
设 c=a^b=gcd(a,b)
发现 c=a-b
证明该结论成立
对于c=a^b>=a-b,
对于在同一个数位相同的二进制位值,xor和减法的效果都是一样的。
对于在同一个数位不同的二进制位值,xor恒等于1,而减法可能向高位借1.
对于c=gcd(a,b)<=a-b (假设a>b)
因为gcd(a,b)=gcd(b,a%b)
设a=qb+r r=a%b=a-qb
gcd(b,a%b)=gcd(b,a-qb)
此时最大公因数不会超过a-qb
而a-qb<=a-b
所以gcd(a,b)=gcd(b,a%b)<=a-b
故满足上述条件的c==a-b
有gcd这一层的关系在
可以让a成为c的倍数来筛选
又使用c=a-b的关系,设a=nc,
则gcd(a,b)=gcd(a,a-c)=gcd(nc,(n-1)c)=c ——因为n与n-1互质
所以接下来只需要验证a^b==c即可
有一点不知你们注意到没,cnt++的位置是a——默认的较大的数
因为a,b均应当满足小于等于n的条件,所以应当记在a的位置
/*SE:wn------王宁*/
#include
using namespace std;
const int maxn = 30000000+1;
int cnt[maxn];
int sum[maxn];
int main()
{
int i,j,n,runs,run,a,b,c;
memset(cnt,0,sizeof(cnt)); memset(sum,0,sizeof(sum));
/*总结:利用约数的性质实现筛法
第一种做法使用了
1.打印结果找规律 2.利用数学证明该规律成立
该规律是:如果gcd(a,b)==a^b,那么c=a-b
3.知晓规律后我们使用c=a-b来推导b
那么这个b=a-c背后的含义是什么呢?
书上是说gcd(a,b)=gcd(a,a-c)=c
所以这个b=a-c明面上确认了gcd(a,b)==c这个条件
为c==a^b的成立提供了可能
小结:要使条件成立,b必须等于a-c
有了这个前提后,gcd部分一定成立*/
for(c=1;c<=15000000;c++)
for(a=c*2;a<=30000000;a+=c)
{
b=a-c;
if(c==(a^b)) ++cnt[a]; //1080ms
/*b=a^c;
if(b%c==0&&b