洛谷P1348 Couple number

洛谷P1348 Couple number

emmm很容易去想用暴力去解题啊……但是看上去这题正解就不是暴力了~

首先要明确平方差公式这一存在

a^2-b^2=(a+b)(a-b)

二话不说打个表看看规律

#include<cstdio>
using namespace std;
int main(){
	freopen("in.txt","w",stdout);
	for(int i=0;i<20;i++){
		for(int j=i;j<20;j++)
			printf("%d ",j*j-i*i); 
		puts("");
	}
	
	return 0;
}
0 1  4  9  16  25  36  49  64  81  100 121 144 169 196 225 256 289 324 361 
0 3  8  15 24  35  48  63  80  99  120 143 168 195 224 255 288 323 360 
0 5  12 21 32  45  60  77  96  117 140 165 192 221 252 285 320 357 
0 7  16 27 40  55  72  91  112 135 160 187 216 247 280 315 352 
0 9  20 33 48  65  84  105 128 153 180 209 240 273 308 345 
0 11 24 39 56  75  96  119 144 171 200 231 264 299 336 
0 13 28 45 64  85  108 133 160 189 220 253 288 325 
0 15 32 51 72  95  120 147 176 207 240 275 312 
0 17 36 57 80  105 132 161 192 225 260 297 
0 19 40 63 88  115 144 175 208 243 280 
0 21 44 69 96  125 156 189 224 261 
0 23 48 75 104 135 168 203 240 
0 25 52 81 112 145 180 217 
0 27 56 87 120 155 192 
0 29 60 93 128 165 
0 31 64 99 136 
0 33 68 105 
0 35 72 
0 37 
0 

从第一列可以看出0是一个CP数;

证明:
	N=a^2-b^2
    当a=b时a^2=b^2
    所以N=0

从第二列可以看出数由1开始递增,而且是所有的奇数

又这列都是由(a+1)2与a2的差

证明:
	N=a^2-b^2
    当a=b+1时
    N=(b+1)^2-b^2=b^+2b+1-b^=2b+1
    当b为任意非负数时,N可以为任意奇数
证明2:
	(a+b)(a-b)=N
    (a+b)与(a-b)的奇偶性一致
    所以(a+b)和(a-b)都是奇数时
    他们的积也一定是奇数!

然后第三列全是偶数,而且都是4的倍数,其他非奇数列都满足是4的倍数这一性质,于是猜想:CP数是奇数+4的倍数

为了证明所有CP数中的非奇数(也就是偶数)全是4的倍数

于是写了程序用来验证

#include<cstdio>
using namespace std;
int main(){
	freopen("in.txt","r",stdin);
	for(int i=1;i<=10000;i++){
		if(i%2==0){
			if(i%4!=0){
				puts("NO");
				return 0;
			}
		}
	}
	puts("YES");
	return 0;
}

程序最后输出YES

证明:
	(a+b)(a-b)=N
    (a+b)与(a-b)的奇偶性一致
    所以当(a+b)与(a-b)都是偶数时
    (a+b)和(a-b)都是2的倍数
    所以两数相乘必有2*2=4
    所以两数会被4整除

证出CP数的性质后就可以上代码了!

#include<cstdio>
using namespace std;
int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    int ans=0;
    for(int i=a;i<=b;i++){
        if(i&1==1)ans++;
        else{
            if(i%4==0)ans++; 
        } 
    }
    printf("%d",ans);
    return 0;
}

这里是枚举了这个给定范围的所有数,然后判断是否是奇数或者4的倍数

虽然这份代码能AC这道题

但是如果数据范围一大1e9那种级别的

岂不是很尴尬~~~

所以有没有公式能直接算出来呢??

#include<cstdio>
using namespace std;
int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    int c=a,d=b;
    int ans=0;
    if(a%2==0)a++;
    if(b%2==0)b--;
    if(a<=b)ans=(b-a)/2+1;
    while(c%4!=0)c++;
    while(d%4!=0)d--;
    if(c<=d)ans+=(d-c)/4+1;
    printf("%d",ans);
    return 0;
}

这样时间上就大大的节约了!

posted @ 2018-02-25 21:59  Neworld1111  阅读(270)  评论(0编辑  收藏  举报