USACO 2.2

USACO 2.2.1 

题解:

先模拟将阿拉伯数字转化为罗马数组,再统计就好了。

代码:

{
ID:m1599491
PROG:preface
LANG:PASCAL
}
const Rome:array[1..13] of string[2]=('M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I');
const Arab:array[1..13] of longint=(1000,900,500,400,100,90,50,40,10,9,5,4,1);
var n,i,j:longint;
var s:string;
var sum:array[1..7] of longint;
var chara:array[1..7] of char=('I','V','X','L','C','D','M');
function ch(x:longint):string;
var i:longint;
var R:string;
begin
  R:='';
  for i:=1 to 13 do
  while x>=Arab[i] do
  begin
    R:=R+Rome[i];
    x:=x-Arab[i];
  end;
  exit(R);
end;
function num(s:string):byte;
begin
  if s='I' then exit(1);if s='V' then exit(2);
  if s='X' then exit(3);if s='L' then exit(4);
  if s='C' then exit(5);if s='D' then exit(6);
  if s='M' then exit(7);
end;
begin
  assign(input,'preface.in');reset(input);
  assign(output,'preface.out');rewrite(output);
  readln(n);
  for i:=1 to n do
  begin
    s:=ch(i);
    for j:=1 to length(s) do inc(sum[num(s[j])]);
  end;
  for i:=1 to 7 do if sum[i]<>0 then writeln(chara[i],' ',sum[i]);
  close(input);close(output);
end.
Preface Numbering

 

USACO 2.2.2

题解:

题目要求的是将一个集合(1...N)划分成两个和相等的集合的方案数,那么就相当于在N个数里面找出和为∑(1...N)*½的组数,就是背包咯。(还可以特判下∑(1...N)如果为奇数就直接输出0

代码:

{
ID:m1599491
PROG:subset
LANG:PASCAL
}
var n,m,i,j:longint;
var f:array[0..39,0..390] of longint;
begin
  assign(input,'subset.in');reset(input);
  assign(output,'subset.out');rewrite(output);
  readln(n);
  m:=(n+1)*n>>1;
  if m and 1=1 then begin writeln(0);close(input);close(output);halt; end;
  m:=m>>1;
  f[0,0]:=1;
  for i:=1 to n do for j:=1 to m do
  if j>=i then f[i,j]:=f[i-1,j]+f[i-1,j-i] else f[i,j]:=f[i-1,j];
  writeln(f[n,m]);
  close(input);close(output);
end.
Subset Sums

 

USACO 2.2.3

题解:

xjb模拟就好咯,之前自己的代码A了之后忘了保存,就copy了别人的(逃

代码:

/*
ID:m1599491
PROG:runround
LANG:C++
*/ 
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int q[10000],front,rear;
int vis[20];int bis[20];
 
int ok(long x)
{
    memset(vis,0,sizeof(vis));
    memset(bis,0,sizeof(bis));
    int k=(int)log10(x)+1;  
    int kk=1;
    while(x>0)
    {
        if(!(x%10)) return 0;
        q[k-kk]=x%10;
        kk++;x/=10;
 
    }
 
    for(int i=0;i<k;i++) vis[q[i]]++;
    for(int i=1;i<10;i++) if(vis[i]>1) return 0;
    front=0;rear=k;
    for(int i=0;i<k;i++)
    {
        int j=q[front];
        bis[j]++;
        if(bis[j]>1) return 0;
        front=(front+j)%k;
    }
    if(front!=0) return 0;
    return 1;
} 
 
int main()
{
    freopen("runround.in","r",stdin);
    freopen("runround.out","w",stdout);
    memset(q,0,sizeof(q));
    long n;
    scanf("%d",&n);
    for(long i=n+1;;i++) if(ok(i))
    {
        printf("%d\n",i);
        break;
    }
    return 0; 
}
Runaround Numbers

 

USACO 2.2.4

题解:

这道题有点强。

仔细想想会发现:1+2=3;1+3=2;2+3=1;1+2+3=啥都没做;同一个按键按两次=啥都没做。这样一来,你会发现不管你怎么xjb按,最终都可以化简为以下8种情况:1,2,3,4,1+4,2+4,3+4,不按(C=0)。

所以只要C>2就统统可以化为0≤C≤2的情况。

当C=0:不按;当C=1:1,2,3,4;当C=2:1+4,2+4,3+3。

然后还有一个特点就是,1号灯永远等于7号灯,2号灯永远等于8号灯,……,i号灯永远等于i+6号灯,这样子就只需要求出前6位(000000,001110,010101,011011,100100,101010,110001),后面的循环输出就好。

代码:

/*
LANG:C++
PROG:lamps
ID:m1599491
*/
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int n,c,i,j,k,A[10],B[10],on[1000];
string s[10];
bool fflag=0;

bool OK(int x)
{
    if (c>2) return 1;
    if (c==0 && x==7) return 1;
    if (c==1 && (x==0 || x==2 || x==3 || x==5)) return 1;
    if (c==2 && (x==1 || x==4 || x==6)) return 1;
    return 0;
}

void writeln(int n,int x)
{
    int point=0;
    fflag=1;
    while (n)
    {
        printf("%d",s[x][point]-48);
        if (point==5) point=0; else point++;
        n--;
    }
    printf("\n");
}

main()
{
    freopen("lamps.in","r",stdin);
    freopen("lamps.out","w",stdout);
    scanf("%d",&n);scanf("%d",&c);
    for (i=1; i<=n; i++) on[i]=2;
    scanf("%d",&k);while (k>-1) {on[k]=1;scanf("%d",&k);}
    scanf("%d",&k);while (k>-1) {on[k]=0;scanf("%d",&k);}
    s[0]="000000";s[1]="001110";s[2]="010101";s[3]="011011";s[4]="100100";s[5]="101010";s[6]="110001";s[7]="111111";
    for (i=1; i<=6; i++) B[i]=2;
    for (i=1; i<=n; i++)
    {
        if (i%6==0){if (on[i]==1) B[6]=1;if (on[i]==0) B[6]=0;}
        else {if (on[i]==1) B[i%6]=1;if (on[i]==0) B[i%6]=0;}
    }
    for (i=0; i<=7; i++)
    {
        bool flag=0;
        for (j=0; j<6; j++) {if (B[j+1]!=2 && B[j+1]!=s[i][j]-48) flag=1;}
        if (!flag && OK(i)) writeln(n,i);
    }
    if (!fflag) printf("IMPOSSIBLE\n");
    return 0;
}
Party Lamps
posted @ 2017-07-27 17:25  ALHDLIOX  阅读(169)  评论(0编辑  收藏  举报