【USACO1.5】解题报告

前言

这章只有两道题,但是质量都不比上一章低。
第一题正解肯定很难,但是数据神奇般的把 O ( n 4 ) O(n^4) O(n4) O ( 25 0 4 ) O(250^4) O(2504)的程序过掉了。。。
第二题标准的深搜。
USACO:http://train.usaco.org


1.5.2.Arithmetic Progressions

这里只能给出神奇的卡常解法。对于想找正解的 O I e r OIer OIer们感到非常抱歉。
首先需要证明当 n ≥ 4 n\geq 4 n4时有 4 ∣ b 4|b 4b。这里给出题解的证明,非常简洁明了。

p = a 2 + b 2 p=a^2+b^2 p=a2+b2
1.当 a , b a,b a,b为偶数。设 a = 2 m , b = 2 m a=2m,b=2m a=2m,b=2m,则 p = 4 ( m 2 + n 2 ) p=4(m^2+n^2) p=4(m2+n2)
2.当 a , b a,b a,b一奇一偶。不妨令 a = 2 m + 1 , b = 2 n a=2m+1,b=2n a=2m+1,b=2n,则 p = 4 ( m 2 + n 2 + m ) + 1 p=4(m^2+n^2+m)+1 p=4(m2+n2+m)+1
3.当 a , b a,b a,b为奇数。设 a = 2 m + 1 , b = 2 n + 1 a=2m+1,b=2n+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 p=4[m(m+1)+n(n+1)]+2
由于 m , m + 1 m,m+1 mm+1中有1个偶数,故 m ( m + 1 ) m(m+1) m(m+1)为偶数,同理, n ( n + 1 ) n(n+1) n(n+1)为偶数,即 m ( m + 1 ) + n ( n + 1 ) m(m+1)+n(n+1) m(m+1)+n(n+1)为偶数,有 p = 8 l + 2 p=8l+2 p=8l+2 l l l为自然数)
p   m o d   4 ≠ 3 p\bmod 4\neq 3 pmod4̸=3.
n > = 4 n>=4 n>=4 b b b为偶数.
4 ∤ b 4\nmid b 4b,则 a a a为偶数。由于能写成 8 l + 6 8l+6 8l+6的形式的数无法写生两个完全平方数的和( 8 l + 6 = 4 ( 2 l + 1 ) + 2 8l+6=4(2l+1)+2 8l+6=4(2l+1)+2),即能 8 l + 6 8l+6 8l+6写成 4 l + 2 4l+2 4l+2的形式,但已证能写成 4 l + 2 4l+2 4l+2形式的数一定不是完全平方数),故 a a a为奇数,矛盾。
4 ∣ b 4\mid b 4b

那么就分成 n &lt; 4 n&lt;4 n<4 n ≥ 4 n\geq 4 n4的两块,前者每次加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 AB
  2. A → C A→C AC
  3. B → A B→A BA
  4. B → C B→C BC
  5. C → A C→A CA
  6. C → B C→B CB
    加上判重即可。

代码:
/*
ID:ssl_zyc2
TASK:milk3
LANG:C++
*/

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

bool p[N][N][N],num[N];
int x,y,z;

void dfs(int a,int b,int c)
{
	if (p[a][b][c]) return;
	p[a][b][c]=1;  //标记
	if (!a) num[c]=1;
	if (a>=y-b) dfs(a-(y-b),y,c);
	 else dfs(0,b+a,c);
	if (a>=z-c) dfs(a-(z-c),b,z);
	 else dfs(0,b,c+a);
	if (b>=x-a) dfs(x,b-(x-a),c);
	 else dfs(a+b,0,c);
	if (b>=z-c) dfs(a,b-(z-c),z);
	 else dfs(a,0,c+b);
	if (c>=x-a) dfs(x,b,c-(x-a));
	 else dfs(a+c,b,0);
	if (c>=y-b) dfs(a,y,c-(y-b));
	 else dfs(a,b+c,0);
}

int main()
{
	freopen("milk3.in","r",stdin);
	freopen("milk3.out","w",stdout);
	scanf("%d%d%d",&x,&y,&z);
	dfs(0,0,z);
	bool writed=0;
	for (int i=0;i<=z;i++)
	 if (num[i]) 
	 {
	 	if (writed) printf(" ");  //因为USACO不允许多余空格和换行,所以要小心
	 	printf("%d",i);
	 	writed=1;
	 }
	printf("\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值