1. 程式人生 > >【USACO1.5】解題報告

【USACO1.5】解題報告

前言

這章只有兩道題,但是質量都不比上一章低。
第一題正解肯定很難,但是資料神奇般的把 O ( n 4 ) O(n^4) O

( 25 0 4 ) O(250^4) 的程式過掉了。。。
第二題標準的深搜。
USACO:http://train.usaco.org


1.5.2.Arithmetic Progressions

這裡只能給出神奇的卡常解法。對於想找正解的 O I e r OIer 們感到非常抱歉。
首先需要證明當 n

4 n\geq 4 時有 4 b 4|b 。這裡給出題解的證明,非常簡潔明瞭。

p = a 2 + b 2 p=a^2+b^2
1.當 a , b a,b 為偶數。設 a = 2 m , b = 2 m a=2m,b=2m ,則 p = 4 ( m 2 + n 2 ) p=4(m^2+n^2)
2.當 a , b a,b 一奇一偶。不妨令 a = 2 m + 1 , b = 2 n a=2m+1,b=2n ,則 p = 4 ( m 2 + n 2 + m ) + 1 p=4(m^2+n^2+m)+1
3.當 a , b a,b 為奇數。設 a = 2 m + 1 , b = 2 n + 1 a=2m+1,b=2n+1 ,則 p = 4 [ m ( m + 1 ) + n ( n + 1 ) ] + 2 p=4[m(m+1)+n(n+1)]+2
由於 m m + 1 m,m+1 中有1個偶數,故 m ( m + 1 ) m(m+1) 為偶數,同理, n ( n + 1 ) n(n+1) 為偶數,即 m ( m + 1 ) + n ( n + 1 ) m(m+1)+n(n+1) 為偶數,有 p = 8 l + 2 p=8l+2 l l 為自然數)
p   m o d   4 3 p\bmod 4\neq 3 .
n > = 4 n>=4 b b 為偶數.
4 b 4\nmid b ,則 a a 為偶數。由於能寫成 8 l + 6 8l+6 的形式的數無法寫生兩個完全平方數的和( 8 l + 6 = 4 ( 2 l + 1 ) + 2 8l+6=4(2l+1)+2 ),即能 8 l + 6 8l+6 寫成 4 l + 2 4l+2 的形式,但已證能寫成 4 l + 2 4l+2 形式的數一定不是完全平方數),故 a a 為奇數,矛盾。
4 b 4\mid b

那麼就分成 n < 4 n<4 n 4 n\geq 4 的兩塊,前者每次加1,後者每次加4就可以了。

程式碼:

/*
ID:ssl_zyc2
TASK:ariprog
LANG:C++
*/

#include <cstdio>
#define N 135010
using namespace std;

int n,m,p[N],maxn,ok,OK;

int main()
{
	freopen("ariprog.in","r",stdin);
	freopen("ariprog.out","w",stdout);
    scanf("%d%d",&n,&m);
    if (n<4)
    {
        for (register int i=0;i<=m;i++)
     	 for (register int j=0;j<=m;j++)
          p[i*i+j*j]=1;
        for (register int j=1;j<=m*m*2;j++)
         for (register int i=0;i<=m*m*2;i++)
         {
         	if (i+(n-1)*j>m*m*2) break;
         	ok=1;	
         	for (register int k=0;k<n;k++)
         	 if (!p[i+k*j]) 
         	 {
         	 	ok=0;
         	 	break;
         	 }
         	if (ok) 
         	{
         		printf("%d %d\n",i,j);
         		OK=1;
         	}
         } 
    }
    else
    {
        for (register int i=0;i<=m;i++)
         for (register int j=0;j<=m;j++)
          p[i*i+j*j]=1;
        for (register int j=4;j<=m*m*2;j+=4)
         for (register int i=1;i<=m*m*2;i++)
         {
         	if (i+(n-1)*j>m*m*2) break;
         	ok=1;	
         	for (register int k=0;k<n;k++)
         	 if (!p[i+k*j]) 
         	 {
         	 	ok=0;
         	 	break;
         	 }
         	if (ok) 
         	{
         		printf("%d %d\n",i,j);
         		OK=1;
         	}
         } 
    }
    if (!OK) printf("NONE\n");
    return 0;
}

1.5.3.Mother’s Milk

思路:

標準的深搜。每次有六種轉移方法:

  1. A B A→B
  2. A C A→C
  3. B A B→A
  4. B C B→C
  5. C A C→A
  6. C B C→B