开个坑记录一下刷USACO的Training的记录

可能会随时弃坑

只有代码和做法简述

可能没有做法简述


[USACO1.1]你的飞碟在这儿Your Ride Is He…

模拟,细节已忘

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s1[],s2[];
int main()
{
int ss1=,ss2=;
scanf("%s",&s1);
scanf("%s",&s2);
int len1=strlen(s1),len2=strlen(s2);
for(int i=;i<len1;i++)
ss1*=s1[i]-;
for(int i=;i<len2;i++)
ss2*=s2[i]-;
int l1=ss1%,l2=ss2%;
if(l1==l2)
cout<<"GO"<<endl;
else
cout<<"STAY"<<endl;
return ;
}

[USACO1.1]贪婪的送礼者Greedy Gift Givers

模拟,用map减少代码量

#include <iostream>
#include <string>
#include <cstdio>
#include <map> using namespace std ; string s[ ] , ch , s1 ;
int n ;
map<string,int> mp ; int main() {
cin >> n ;
for( int i = ; i <= n ; i ++ ) cin >> s[ i ] , mp[ s[ i ] ] = ;
for( int i = ; i <= n ; i ++ ) {
int val , m ;
cin >> ch >> val >> m ;
if( m != ) val /= m ;
mp[ ch ] -= val * m ;
for( int i = ; i <= m ; i ++ ) {
cin >> s1 ;
mp[ s1 ] += val ;
}
}
for( int i = ; i <= n ; i ++ ) {
cout << s[ i ] << " " << mp[ s[ i ] ] << endl ;
}
}

[USACO1.1]黑色星期五Friday the Thirteenth

恶心模拟,用数学方法算一下规律,然后模拟即可

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
int year,month,i,n,last=;
int dayOfMonth[]={,,,,,,,,,,,};
int result[]={};
cin>>n;
for(year=;year<+n;++year){
if(year%==||(year%!=&&year%==)) dayOfMonth[]=;
for(month=;month<;++month){
last=(last+dayOfMonth[month])%;
result[last]++;
}
dayOfMonth[]=;
}
for(i=;i<;++i) cout<<result[(i+)%]<<' ';
cout<<result[]<<endl;
return ;
}

[USACO1.1]坏掉的项链Broken Necklace

暴力模拟,细节已忘

#include <cstdio>
using namespace std;
int n,ans=-;char a[];
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
void find(int x){
char c=a[x];
int sum=;
for(int i=x;i;i--){
if(a[i]==c)sum++;
else if(a[i]=='w')sum++;
else break;
}
c=a[x+];
for(int i=x+;i<=*n;i++){
if(a[i]==c)sum++;
else if(a[i]=='w')sum++;
else break;
}
ans=max(ans,sum);
}
int main(){
scanf("%d%s",&n,a+);
for(int i=;i<=n;i++){
a[i+n]=a[i];a[i+n+n]=a[i];
}
for(int i=n;i<=*n;i++){
if(a[i]==a[i+])continue;
if(a[i]=='w'){
a[i]='r';
find(i);
a[i]='b';
find(i);
a[i]='w';
}
find(i);
}
ans=min(ans,n);
if(ans==-)ans=n;
printf("%d\n",ans);
return ;
}

[USACO1.2]命名那个数字 Name That Number

看不懂。这题有毒,用的题解的check

#include <iostream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <map> using namespace std ; char ft[][]={{},{},"ABC","DEF","GHI","JKL","MNO","PRS","TUV","WXY"};
string s[ ] ;
int n ; int main() {
while( cin >> s[ n ] ) n ++ ;
string ch = s[ ] ;
n -- ;
sort( s + , s + n + ) ;
bool check = ;
for( int i = ; i <= n ; i ++ ) {
bool ok = ( s[ i ].length() == ch.length() ) ;
for( int j = ; j < s[ i ].length() ; j ++ ) {
char c=s[ i ][ j ] ;
ok = ok & (c==ft[ch[j]-''][] || c==ft[ch[j]-''][] || c==ft[ch[j]-''][]);
}
if( ok ) {
cout << s[ i ] << endl ;
check = ;
}
}
if( check ) cout << "NONE\n" ;
return ;
}

[USACO1.2]挤牛奶Milking Cows

差分一下然后按题目模拟,纯模拟可过,应该是数据水吧

#include <bits/stdc++.h>

using namespace std ;

#define ll long long
#define N 1000010 int n ;
int c[ N ] ; int main() {
scanf( "%d" , &n ) ;
int s = 0x3f3f3f3f , t = ;
for( int i = , l , r ; i <= n ; i ++ ) {
scanf( "%d%d" , &l , &r ) ;
c[ l ] ++ ; c[ r ] -- ;
s = min( s , l ) ;
t = max( t , r - ) ;
}
int ans[ ] = { };
int ch = , now = s ;
t ++ ;
for( int i = s ; i <= t ; i ++ ) {
c[ i ] = c[ i - ] + c[ i ] ;
int x = c[ i ] != ;
if( x != ch || i == t ) {
ans[ ch ] = max( ans[ ch ] , i - now ) ;
now = i ;
ch ^= ;
}
}
printf( "%d %d\n" , ans[ ] , ans[ ] ) ;
return ;
}

[USACO1.2]方块转换 Transformations

恶心模拟题,不写

于是挑了一个下午的自习写掉了这题...

这道题告诉我们在代码大量重复的情况下要善用define......

反正define一下for,然后旋转和翻转打个子程序,代码量也就1kb左右..不这么干我觉得代码量能到3kb

#include <bits/stdc++.h>

using namespace std ;

#define FOR( i , a , b ) for( int i = a ; i <= b ; i ++ )
#define copy( a , b ) memcpy( a , b , sizeof( a ) ) char c[ ][ ] , a[ ][ ] , ans[ ][ ] , t[ ][ ] ;
int n ; void turn() {
copy( t , c ) ;
FOR( i , , n ) FOR( j , , n ) c[ i ][ n - j + ] = t[ j ][ i ] ;
} bool check() {
FOR( i , , n ) FOR( j , , n ) if( c[ i ][ j ] != ans[ i ][ j ] ) return ;
return ;
} void turn2() {
copy( t , c ) ;
FOR( i , , n ) FOR( j , , n ) c[ i ][ n - j + ] = t[ i ][ j ] ;
} int main() {
scanf( "%d" , &n ) ;
FOR( i , , n ) scanf( "%s" , a[ i ] + ) ;
FOR( i , , n ) scanf( "%s" , ans[ i ] + ) ;
copy( c , a ) ; turn() ;
if( check() ) { return puts( "" ) , ; }
copy( c , a ) ; FOR( i , , ) { turn() ; }
if( check() ) { return puts( "" ) , ; }
copy( c , a ) ; FOR( i , , ) { turn() ; }
if( check() ) { return puts( "" ) , ; }
copy( c , a ) ; turn2() ;
if( check() ) { return puts( "" ) , ; }
copy( c , a ) ; turn2() ;
FOR( i , , ) { turn() ; if( check() ) { return puts( "" ) , ; } }
copy( c , a ) ;
if( check() ) { return puts( "" ) , ; }
return puts( "" ) , ;
}

[USACO1.2]回文平方数 Palindromic Squares

坑点就是输出的时候,当前数输出要是B进制数

然后就是进制转换的模拟了

#include <bits/stdc++.h>

using namespace std ;

int n , s ;
int l , t ;
int a[ ] , c[ ] ; bool check( int x , int k ) {
l = , t = x ;
while( t ) {
a[ ++ l ] = t % k ;
t /= k ;
}
for( int i = , j = l ; i <= l / ; i ++ , j -- ) {
if( a[ i ] != a[ j ] ) return ;
}
return ;
} int main() {
scanf( "%d" , &n ) ;
for( int i = ; i <= ; i ++ ) {
if( check( i * i , n ) ) {
int t = i , len = ;
while( t ) {
c[ ++ len ] = t % n ;
t /= n ;
}
for( int i = len ; i ; i -- ) {
if( c[ i ] >= ) putchar( c[ i ] - + 'A' ) ;
else printf( "%d" , c[ i ] ) ;
}
putchar( ' ' ) ;
for( int i = l ; i ; i -- ) {
if( a[ i ] >= ) putchar( a[ i ] - + 'A' ) ;
else printf( "%d" , a[ i ] ) ;
}
puts( "" ) ;
}
}
return ;
}

[USACO1.2]双重回文数 Dual Palindromes

和上一题差不多。

觉得这题更简单点...

#include <bits/stdc++.h>

using namespace std ;

int n , s ;
int a[ ] ; bool check( int x , int k ) {
int l = , t = x ;
while( t ) {
a[ ++ l ] = t % k ;
t /= k ;
}
for( int i = , j = l ; i <= l / ; i ++ , j -- ) {
if( a[ i ] != a[ j ] ) return ;
}
return ;
} int main() {
scanf( "%d%d" , &n , &s ) ;
for( int tot = , i = s + ; tot < n ; i ++ ) {
int cnt = ;
for( int j = ; j <= && cnt < ; j ++ ) {
if( check( i , j ) ) cnt ++ ;
}
if( cnt >= ) {
printf( "%d\n" , i ) ;
tot ++ ;
}
}
return ;
}

[USACO1.3]混合牛奶 Mixing Milk

随便贪心一下的样子

太久了忘记了

可能码风会很丑

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll int
#define maxn 5010
#define inf 1<<30
#define mt(x,y) memset(x,y,sizeof(x))
#define max(x,y) x>y?x:y
#define min(x,y) x<y?x:y
#define abs(x) x>0?x:-x
#define mod 10000007
inline void read(ll &x){x=;ll f=;char c=getchar();while(c<''||c>''){if(c=='-')f=-f;c=getchar();}while(c>=''&&c<=''){x=x*+c-'';c=getchar();}x*=f;}
using namespace std;
/************************************************************************/
//struct edge{ll u,w,v;}e[maxn];
struct node{ll a,b;}a[maxn];
ll n,m,ans=;
/************************************************************************************************************************************/
//inline void add(ll u,ll v,ll w){e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;}
//inline void prime(ll x){mt(prime,1);prime[0]=0;prime[1]=0;for(ll i=2;i<=x;i++){if(prime[i])for(ll j=i+i;j<=x;j+=i)prime[j]=0;}}
//inline ll power(ll a,ll b){ll ans=1,base=a;while(b){if(b&1)ans=ans*base%mod;base=base*base%mod;b>>=1;}return ans;}
//inline ll log(ll x){ll p=1,ans=0;while(p<=x){ans++;p<<=1;}return ans;}
inline bool cmp(node a,node b){return a.a<b.a;}
/************************************************************************************************************************************/
int main(){
read(n);read(m);
for(ll i=;i<=m;i++){
read(a[i].a);read(a[i].b);
}
sort(a+,a+m+,cmp);
for(ll i=;i<=m;i++){
if(a[i].b<n){
n-=a[i].b;
ans+=a[i].a*a[i].b;
}else {
ans+=n*a[i].a;
break;
}
}
printf("%d",ans);
return ;
}

[USACO1.3]修理牛棚 Barn Repair

因为最多只能断$m$个点,所以把每个牛棚之间的差值求出来,然后从大到小断掉$m$个点就好

#include <bits/stdc++.h>

using namespace std ;

#define ll long long
#define N 55010 int n , m , s ;
int a[ N ] , c[ N ] ; bool cmp( int a , int b ) {
return a > b ;
} int main() {
scanf( "%d%d%d" , &m , &s , &n ) ;
for( int i = ; i <= n ; i ++ ) scanf( "%d" , &a[ i ] ) ;
sort( a + , a + n + ) ;
for( int i = ; i <= n ; i ++ ) c[ i - ] = a[ i ] - a[ i - ] ;
sort( c + , c + n + , cmp ) ;
int ans = a[ n ] - a[ ] + ;
for( int i = ; i < m && i < n ; i ++ ) {
ans -= c[ i ] - ;
}
printf( "%d\n" , ans ) ;
}

[USACO1.3]牛式 Prime Cryptarithm

模拟一下竖式运算就行了...

但是好恶心啊...

#include <bits/stdc++.h>

using namespace std ;

#define N 200010

int n ;
int a[ N ] ;
bool vis[ N ] ;
int ans = ; bool check_1( int x ) {
int w[ ] , l = ;
while( x ) {
w[ ++ l ] = x % ;
x /= ;
}
for( int i = ; i <= l ; i ++ ) {
if( !vis[ w[ i ] ] ) return ;
}
return ;
} void check( int x , int y ) {
if( check_1( x ) ) return ;
if( check_1( y ) ) return ;
int w_1 = y % , w_2 = y / ;
if( w_1 * x >= || w_2 * x >= ) return ;
if( x * y >= ) return ;
if( check_1( w_1 * x ) ) return ;
if( check_1( w_2 * x ) ) return ;
if( check_1( x * y ) ) return ;
ans ++ ;
} int main() {
scanf( "%d" , &n ) ;
for(int i = ; i <= n ; i ++ ) {
scanf( "%d" , &a[ i ] ) ;
vis[ a[ i ] ] = ;
}
for( int i = ; i <= ; i ++ ) {
for( int j = ; j <= ; j ++ ) {
check( i , j ) ;
}
}
printf( "%d\n" , ans ) ;
return ;
}

[USACO1.3]虫洞wormhole

用$dfs$枚举配对方案

然后再用$dfs$判一下这种方案能不能走出环

然后注意要把坐标排序一下,不然可能会出现重复方案

#include <bits/stdc++.h>

using namespace std ;

#define N 5010

int n ;
struct node {
int x , y ;
} a[ N ] ;
int b[ N ] ; bool cmp( node a , node b ) {
if( a.y == b.y ) return a.x < b.x ;
return a.y < b.y ;
} bool find( int num , int now , int s , int p ) {
if( num != && now == s && p == ) return ;
if( !p ) {
if( a[ now ].y == a[ now + ].y ) return find( num + , now + , s , ) ;
else return ;
}
if( p ) return find( num + , b[ now ] , s , ) ;
} bool check() {
for( int j = ; j <= n ; j ++ ) {
if( find( , j , j , ) ) return ;
}
return ;
} int ans = ; void dfs( int x ) {
if( x == n + ) {
if( check() ) ans ++ ;
return ;
}
if( b[ x ] == ) {
for( int i = x + ; i <= n ; i ++ ) {
if( b[ i ] == ) {
b[ i ] = x ; b[ x ] = i ;
dfs( x + ) ;
b[ i ] = ; b[ x ] = ;
}
}
}
if( b[ x ] != ) dfs( x + ) ;
} int main() {
scanf( "%d" , &n ) ;
for( int i = ; i <= n ; i ++ ) {
scanf( "%d%d" , &a[ i ].x , &a[ i ].y ) ;
}
sort( a + , a + n + , cmp ) ;
dfs( ) ;
printf( "%d\n" , ans ) ;
return ;
}

[USACO1.3]滑雪课程设计Ski Course Design

枚举最后的最低高度,然后按题意算出每个山峰的贡献就好

对于每个最低高度取个$min$

#include <bits/stdc++.h>

using namespace std ;

#define N 5010

int n ;
int a[ N ] ; int main() {
scanf( "%d" , &n ) ;
for( int i = ; i <= n ; i ++ ) scanf( "%d" , &a[ i ] ) ;
sort( a + , a + n + ) ;
int ans = ;
for( int cnt = ; cnt < ; cnt ++ ) {
int sum = ;
for( int i = ; i <= n ; i ++ ) {
if( a[ i ] < cnt ) sum += ( cnt - a[ i ] ) * ( cnt - a[ i ] ) ;
else {
if( a[ i ] > cnt + ) {
sum += ( a[ i ] - ( cnt + ) ) * ( a[ i ] - ( cnt + ) ) ;
}
}
}
ans = min( ans , sum ) ;
}
printf( "%d\n" , ans ) ;
}

[USACO1.3]号码锁 Combination Lock

直接枚举...

然后两个号码分开来匹配就好了

注意是环形所以要多判一下

#include <bits/stdc++.h>

using namespace std ;

#define N 5010

int n ;
int a[ ] , b[ ] , c[ ] ;
int ans = ; int check() {
int sum = ;
for( int i = ; i < ; i ++ ) {
if( abs( a[ i ] - c[ i ] ) <= ) {
sum ++ ;
} else {
int x = min( a[ i ] , c[ i ] ) , y = max( a[ i ] , c[ i ] ) ;
if( n - y + x <= ) sum ++ ;
}
}
if( sum == ) return ;
sum = ;
for( int i = ; i < ; i ++ ) {
if( abs( b[ i ] - c[ i ] ) <= ) {
sum ++ ;
} else {
int x = min( b[ i ] , c[ i ] ) , y = max( b[ i ] , c[ i ] ) ;
if( n - y + x <= ) sum ++ ;
}
}
if( sum == ) return ;
return ;
} int main() {
scanf( "%d" , &n ) ;
for( int i = ; i < ; i ++ ) scanf( "%d" , &a[ i ] ) ;
for( int i = ; i < ; i ++ ) scanf( "%d" , &b[ i ] ) ;
for( int i = ; i <= n ; i ++ ) {
for( int j = ; j <= n ; j ++ ) {
for( int k = ; k <= n ; k ++ ) {
c[ ] = i ; c[ ] = j ; c[ ] = k ;
ans += check() ;
}
}
}
printf( "%d\n" , ans ) ;
}

[USACO1.4]等差数列 Arithmetic Progressions

一开始打了一个立方的暴力,拿了个55..

然后在题解的点醒下猛然发现可以直接枚举最后两个数,公差就出来了

枚举最后两个数可以剪掉一些枝,就是当最后一个数减掉n*公差小于0就直接跳掉了

#include <bits/stdc++.h>

using namespace std ;

#define N 1000100

int n , m ;
int a[ N ] , b[ N ] ;
struct node {
int x , y ;
} ans[ N ] ; bool cmp1( int a , int b ) {
return a > b ;
} bool cmp2( node a , node b ) {
if( a.y == b.y ) return a.x < b.x ;
return a.y < b.y ;
} int main() {
scanf( "%d%d" , &n , &m ) ;
int tot = ;
for( int i = ; i <= m ; i ++ ) {
for( int j = ; j <= m ; j ++ ) {
if( !b[ i * i + j * j ] ) a[ ++ tot ] = i * i + j * j ;
b[ i * i + j * j ] = ;
}
}
int cnt = ;
sort( a + , a + tot + , cmp1 ) ;
for( int i = ; i <= tot - n + ; i ++ ) {
for( int j = i + ; j <= tot - n + ; j ++ ) {
int c = a[ i ] - a[ j ] , now = a[ j ] , t = n - , flag = ;
if( now - t * c < ) continue ;
while( t ) {
t -- ;
now -= c ;
if( !b[ now ] ) { flag = ; break ; }
}
if( !flag ) continue ;
ans[ ++ cnt ].x = now , ans[ cnt ].y = c ;
}
}
if( !cnt ) return puts("NONE") , ;
sort( ans + , ans + cnt + , cmp2 ) ;
for( int i = ; i <= cnt ; i ++ ) {
printf( "%d %d\n" , ans[ i ].x , ans[ i ].y ) ;
}
return ;
}

[USACO1.4]母亲的牛奶 Mother's Milk

就是爆搜出每个状态。不过感觉$dfs$不是很好打就打了$bfs$

然后可以给每个状态编个号,可以大量简化代码

#include <bits/stdc++.h>

using namespace std ;

int a , b , c ;
int ans[ ] ;
int vis[ ][ ][ ] ;
int q[ ][ ] ; int main() {
scanf( "%d%d%d" , &a , &b , &c ) ;
vis[ ][ ][ c ] = ;
int l = , r = ;
q[ l ][ ] = , q[ l ][ ] = , q[ l ][ ] = c ;
ans[ c ] = ;
while( l != r ) {
for( int i = ; i < ; i ++ ) {
int xa = q[ l ][ ] , xb = q[ l ][ ] , xc = q[ l ][ ] ;
int w , now1 = i / , now2 = i % ;
// now1 从now1桶倒出
// now2 倒进now2桶
// 0,1,2 对应 a,b,c
if( now1 == now2 ) continue ;
if( now1 == ) { // 从1桶倒出
w = xa ;
if( now2 == ) { xb = min( q[ l ][ ] + w , b ) ; xa = max( xa - ( b - q[ l ][ ] ) , ) ; }
if( now2 == ) { xc = min( q[ l ][ ] + w , c ) ; xa = max( xa - ( c - q[ l ][ ] ) , ) ; }
}
if( now1 == ) { // 从2桶倒出
w = xb ;
if( now2 == ) { xa = min( q[ l ][ ] + w , a ) ; xb = max( xb - ( a - q[ l ][ ] ) , ) ; }
if( now2 == ) { xc = min( q[ l ][ ] + w , c ) ; xb = max( xb - ( c - q[ l ][ ] ) , ) ; }
}
if( now1 == ) {
w = xc ;
if( now2 == ) { xa = min( q[ l ][ ] + w , a ) ; xc = max( xc - ( a - q[ l ][ ] ) , ) ; }
if( now2 == ) { xb = min( q[ l ][ ] + w , b ) ; xc = max( xc - ( b - q[ l ][ ] ) , ) ; }
}
if( vis[ xa ][ xb ][ xc ] || !w ) continue ;
vis[ xa ][ xb ][ xc ] = ;
if( xa == ) ans[ xc ] = ;
q[ r ][ ] = xa , q[ r ][ ] = xb , q[ r ][ ] = xc ;
r ++ ;
if( r == ) r = ;
}
l ++ ;
if( l == ) l = ;
}
for( int i = ; i <= ; i ++ ) {
if( ans[ i ] ) printf( "%d " , i ) ;
}
return ;
}

[USACO1.5]数字三角形 Number Triangles

dp入门题

#include <iostream>
#include <cstring>
using namespace std;
int f[][],a[][];
int n;
int main(){
cin>>n;
memset(f,,sizeof(f));
memset(a,,sizeof(a));
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
cin>>a[i][j];
}
}
f[][]=a[][];
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
if(j==)f[i][j]=f[i-][j]+a[i][j];
else if(j==i)f[i][j]=f[i-][j-]+a[i][j];
else f[i][j]=max(f[i-][j],f[i-][j-])+a[i][j];
}
}
int ans=;
for(int i=;i<=n;i++){
ans=max(ans,f[n][i]);
}
cout<<ans<<endl;
return ;
}

[USACO1.5]回文质数 Prime Palindromes

其实这题正解应该是$dfs$构造出回文数来然后判断素数什么的

但是懒得写啊

所以就投机取巧一下

因为是回文素数,所以可以先判是否回文(在这题里面判断回文最大复杂度也就$O(16)$),不是就跳掉

用$O(\sqrt{n})$的时间判掉是不是素数

然后开个$O2$卡卡也就过去了

然而洛谷人才真的多

可以判掉上界,因为$1e8$里面的回文素数最大是$9989899$

所以可以直接大于这个数的上界砍掉

那么不开$O2$也能稳稳过掉了

#include <bits/stdc++.h>

using namespace std ;

int a , b ;
int num[ ] ; bool is_prime( int x ) {
int m = sqrt( x ) ;
for( int i = ; i <= m ; i ++ ) {
if( x % i == ) return ;
}
return ;
} bool check( int x ) {
int l = ;
while( x ) {
num[ ++ l ] = x % ;
x /= ;
}
for( int i = , j = l ; i <= l / ; i ++ , j -- ) {
if( num[ i ] != num[ j ] ) return ;
}
return ;
} int main() {
scanf( "%d%d" , &a , &b ) ;
if( a % == ) a ++ ;
if( b >= (int)1e8 ) b = ;
for( int i = a ; i <= b ; i += ) {
if( check( i ) && is_prime( i ) ) printf( "%d\n" , i ) ;
}
}

[USACO1.5]特殊的质数肋骨 Superprime Rib

这题随便搜一下就好了...

就是最高位不能是1和9注意判掉就行

#include <bits/stdc++.h>

using namespace std ;

int n ;
int ans[ ] ;
int num[ ] ;
int p[] = { , , , , , , } ; bool is_prime( int x ) {
int m = sqrt( x ) ;
for( int i = ; i <= m ; i ++ ) {
if( x % i == ) return ;
}
return ;
} bool check( int x ) {
int ans = , l = ;
for( int i = x ; i ; i -- ) {
ans += num[ i ] * l ;
l *= ;
}
if( is_prime( ans ) ) return ;
return ;
} int cnt = ; void print() {
int sum = , l = ;
for( int i = n ; i ; i -- ) {
sum += l * num[ i ] ;
l *= ;
}
ans[ ++ cnt ] = sum ;
} void dfs( int x ) {
if( x == n + ) {
print() ;
return ;
}
for( int i = ; i <= ; i ++ ) {
if( x == && ( i == || i == ) ) continue ;
num[ x ] = p[ i ] ;
if( x != && !check( x ) ) continue ;
dfs( x + ) ;
num[ x ] = ;
}
} int main() {
scanf( "%d" , &n ) ;
dfs( ) ;
sort( ans + , ans + cnt + ) ;
for( int i = ; i <= cnt ; i ++ ) printf( "%d\n" , ans[ i ] ) ;
}

城堡 The Castle

它让我考虑弃掉$usaco-training$了...

我$debug$了一天...,写了$4kb+$

就是搜索

第一二问随便写。我一开始直接写了一个联通块的染色

然后发现不能用邻接表不然没法求$3,4$问,于是重新码

然后搞3,4问差不多2,3h。。对着题解debug出来的

先处理墙在上面的情况,然后再处理墙在旁边的情况,注意顺序不能乱...

我就不知道他为什么不要直接弄个$SPJ$,或者是干脆不要方案啊......

这$4kb+$代码全都是血和泪...

#include <bits/stdc++.h>

using namespace std ;

const int dx[] = {  , - ,  ,  } ;
const int dy[] = { - , , , } ; int ans[ ] = { , , , } ;
int Ans = ; struct node {
int u , d , l , r ;
} t[ ][ ] ;
int a[ ][ ] ;
int n , m ;
int tot = ;
int belong[ ][ ] ;
int num[ ] ; bool check( int x , int y ) {
if( x < || x > n || y < || y > m ) return ;
if( belong[ x ][ y ] ) return ;
return ;
} void dfs( int x , int y , int c ) {
belong[ x ][ y ] = c ;
num[ c ] ++ ;
for( int i = ; i < ; i ++ ) {
if( ! ( a[ x ][ y ] & ( << i ) ) ){
int nx = x + dx[ i ] , ny = y + dy[ i ] ;
if( check( nx , ny ) ) dfs( nx , ny , c ) ;
}
}
} bool check_1( int x , int y ) {
if( num[ belong[ x ][ y ] ] + num[ belong[ x ][ y - ] ] > ans[ ] )
return ;
if( num[ belong[ x ][ y ] ] + num[ belong[ x ][ y - ] ] == ans[ ] && y - < ans[ ] )
return ;
if( num[ belong[ x ][ y ] ] + num[ belong[ x ][ y - ] ] == ans[ ] && y - == ans[ ] && x > ans[ ] )
return ;
return ;
} bool check_2( int x , int y ) {
if( num[ belong[ x ][ y ] ] + num[ belong[ x - ][ y ] ] > ans[ ] )
return ;
if( num[ belong[ x ][ y ] ] + num[ belong[ x - ][ y ] ] == ans[ ] && y < ans[ ] )
return ;
if( num[ belong[ x ][ y ] ] + num[ belong[ x - ][ y ] ] == ans[ ] && y == ans[ ] && x > ans[ ] )
return ;
return ;
} int main() {
scanf( "%d%d" , &m , &n ) ;
for( int i = ; i <= n ; i ++ ) {
for( int j = ; j <= m ; j ++ ) {
scanf( "%d" , &a[ i ][ j ] ) ;
int t1 = a[ i ][ j ] ;
if( t1 - >= ) t[ i ][ j ].d = , t1 -= ;
if( t1 - >= ) t[ i ][ j ].r = , t1 -= ;
if( t1 - >= ) t[ i ][ j ].u = , t1 -= ;
if( t1 - >= ) t[ i ][ j ].l = , t1 -= ;
}
}
for( int i = ; i <= n ; i ++ ) {
for( int j = ; j <= m ; j ++ ) {
if( belong[ i ][ j ] ) continue ;
dfs( i , j , ++ tot ) ;
}
}
for( int i = ; i <= tot ; i ++ ) Ans = max( Ans , num[ i ] ) ;
printf( "%d\n%d\n" , tot , Ans ) ;
for( int i = ; i <= n ; i ++ ) {
for( int j = ; j <= m ; j ++ ) {
if( t[ i ][ j ].l && belong[ i ][ j ] != belong[ i ][ j - ] ) {
if( check_1( i , j ) ) {
ans[ ] = num[ belong[ i ][ j ] ] + num[ belong[ i ][ j - ] ] ;
ans[ ] = i ; ans[ ] = j - ;
ans[ ] = 'E' ;
}
}
if( t[ i ][ j ].u && belong[ i ][ j ] != belong[ i - ][ j ] ) {
if( check_2( i , j ) ) {
ans[ ] = num[ belong[ i ][ j ] ] + num[ belong[ i - ][ j ] ] ;
ans[ ] = i ; ans[ ] = j ;
ans[ ] = 'N' ;
}
}
}
}
printf( "%d\n%d %d %c\n" , ans[ ] , ans[ ] , ans[ ] , ans[ ] ) ;
}

顺序的分数 Ordered Fractions

这题随便做...

枚举分子和分母,判一下$gcd$

然后转成小数排序输出就可以了

分母不能为0

#include <bits/stdc++.h>

using namespace std ;

int n , cnt =  ;
struct node {
double val ;
int x , y ;
} fac[ ] ; int gcd( int a , int b ) {
if( b == ) return a ;
return gcd( b , a % b ) ;
} bool cmp( node a , node b ) {
return a.val < b.val ;
} int main() {
scanf( "%d" , &n ) ;
for( int i = ; i <= n ; i ++ ) {
for( int j = ; j <= i ; j ++ ) {
if( gcd( j , i ) == ) {
fac[ ++ cnt ].x = j ;
fac[ cnt ].y = i ;
fac[ cnt ].val = (double)fac[ cnt ].x / (double)fac[ cnt ].y ;
}
}
}
sort( fac + , fac + cnt + , cmp ) ;
for( int i = ; i <= cnt ; i ++ ) {
printf( "%d/%d\n" , fac[ i ].x , fac[ i ].y ) ;
}
return ;
}

三值的排序 Sorting a Three-Valued Sequence

这题有点思维..

考虑最后得到的序列

一定是$1112223333$这样子的

那么就可以把最终序列划分成三段

对于出现在1,2段的3,显然只要一次交换就能换到第三段那里

然后对于1出现在2的情况,2出现在1的情况,也是要交换的,不过对于这两种情况只需要取个$max$就好了,因为两者是可以互相抵消的

#include <bits/stdc++.h>

using namespace std ;

int n ;
int a[ ] ;
int cnt[ ] , num[ ] ; int main() {
scanf( "%d" , &n ) ;
for( int i = ; i <= n ; i ++ )
scanf( "%d" , &a[ i ] ) , cnt[ a[ i ] ] ++ ;
for( int i = ; i <= cnt[ ] + cnt[ ] ; i ++ ) {
if( a[ i ] == ) num[ ] ++ ;
else if( a[ i ] == && i <= cnt[ ] ) num[ ] ++ ;
else if( a[ i ] == && i > cnt[ ] ) num[ ] ++ ;
}
printf( "%d\n" , num[ ] + max( num[ ] , num[ ] ) ) ;
}

健康的荷斯坦奶牛 Healthy Holsteins

数据范围很小,所以直接爆搜所有状态即可

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <cstdlib> using namespace std ; #define N 30 int v , n ;
int t[ N ] ;
int a[ N ][ N ] ;
int num[ N ] ;
int now[ N ] ;
int ans = , Ans[ N ] ; void dfs( int x , int p ) {
bool flag = ;
now[ p ] = x ;
for( int i = ; i <= v ; i ++ ) {
num[ i ] += a[ x ][ i ] ;
if( num[ i ] < t[ i ] ) flag = ;
}
if( flag ) {
if( p < ans ) {
ans = p ;
for( int i = ; i <= p ; i ++ ) {
Ans[ i ] = now[ i ] ;
}
}
return ;
}
for( int i = x + ; i <= n ; i ++ ) {
dfs( i , p + ) ;
for( int k = ; k <= v ; k ++ ) {
num[ k ] -= a[ i ][ k ] ;
}
}
} int main() {
scanf( "%d" , &v ) ;
for( int i = ; i <= v ; i ++ ) scanf( "%d" , &t[ i ] ) ;
scanf( "%d" , &n ) ;
for( int i = ; i <= n ; i ++ ) {
for( int j = ; j <= v ; j ++ ) {
scanf( "%d" , &a[ i ][ j ] ) ;
}
}
for( int i = ; i <= n ; i ++ ) {
memset( now , , sizeof( now ) ) ;
memset( num , , sizeof( num ) ) ;
dfs( i , ) ;
}
printf( "%d " , ans ) ;
for( int i = ; i <= ans ; i ++ ) printf( "%d " , Ans[ i ] ) ;
puts( "" ) ;
return ;
}

海明码 Hamming Codes

可以有前导零,所以直接从1开始枚举就好了...而0一定在答案里面

对于是否符合要求,直接暴力判断

#include <bits/stdc++.h>

using namespace std ;

int n , b , d ;
int ans[ ] ; int main() {
scanf( "%d%d%d" , &n , &b , &d ) ;
int tot = ;
ans[ ] = ;
for( int i = ; tot < n ; i ++ ) {
bool flag = ;
for( int j = ; j <= tot ; j ++ ) {
int sum = ;
for( int k = ; k >= ; k -- ) {
if( ( ( ans[ j ] >> k ) & ) ^ ( ( i >> k ) & ) )
sum ++ ;
}
if( sum < d ) { flag = ; break ; }
}
if( flag == ) {
ans[ ++ tot ] = i ;
}
}
for( int i = ; i <= n ; i ++ ) {
printf( "%d " , ans[ i ] ) ;
if( !( i % ) ) putchar( '\n' ) ;
}
return ;
}

序言页码 Preface Numbering

打表题...感觉没啥意义,所以就直接抄了$lmh$大爷的表就跳下一题了

#include <bits/stdc++.h>

using namespace std ;

const char *A[]={" ", "I ", "II ", "III ", "IV ", "V ", "VI ", "VII ", "VIII ", "IX "};
const char *B[]={" ", "X ", "XX ", "XXX ", "XL ", "L ", "LX ", "LXX ", "LXXX ", "XC "};
const char *C[]={" ", "C ", "CC ", "CCC ", "CD ", "D ", "DC ", "DCC ", "DCCC ", "CM "};
const char *D[]={" ", "M ", "MM ", "MMM "};
const char *S="IVXLCDM "; int n ;
int c[ ] ; int main() {
scanf( "%d" , &n ) ;
for( int i = ; i <= n ; i ++ ) {
int tmp = i ;
for( int j = ; A[ tmp % ][ j ] ^ ' ' ; j ++ ) c[ A[ tmp % ][ j ] ] ++ ;
tmp /= ;
for( int j = ; B[ tmp % ][ j ] ^ ' ' ; j ++ ) c[ B[ tmp % ][ j ] ] ++ ;
tmp /= ;
for( int j = ; C[ tmp % ][ j ] ^ ' ' ; j ++ ) c[ C[ tmp % ][ j ] ] ++ ;
tmp /= ;
for( int j = ; D[ tmp % ][ j ] ^ ' ' ; j ++ ) c[ D[ tmp % ][ j ] ] ++ ;
tmp /= ;
}
for( int i = ; S[ i ] ^ ' ' ; i ++ ) if( c[ S[ i ] ] ) printf( "%c %d\n" , S[ i ] , c[ S[ i ] ] ) ;
}

循环数 Runaround Numbers

直接从$m$向后枚举,感觉效率过不去但是实际上过得去...

#include <bits/stdc++.h>

using namespace std ;

int m ;
int a[ ] , len , t[ ] ;
int vis[ ] ; bool check() {
int now = ;
for( int i = ; i <= len ; i ++ ) {
if( vis[ a[ now ] ] || a[ now ] == ) return ;
vis[ a[ now ] ] ++ ;
now = ( now + a[ now ] - ) % len + ;
}
if( now != ) return ;
return ;
} int main() {
scanf( "%d" , &m ) ;
while( ) {
int x = ++m ;
len = ;
while( x ) {
t[ ++ len ] = x % ;
x /= ;
}
for( int i = ; i <= len ; i ++ ) a[ i ] = t[ len - i + ] ;
memset( vis , , sizeof( vis ) ) ;
if( check() ) return printf( "%d" , m ) , ;
}
}

派对灯 Party Lamps

有点恶心,貌似是分类讨论然后模拟

后面再补


最长前缀 Longest Prefix

因为给的那几个用来匹配模式串的串很小,所以直接暴力dp暴力check即可

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f
#define il inline #define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a )
#define outn(a) out(a),putchar('\n') #define I_int int
inline I_int read() { I_int x = , f = ; char c = getchar() ;
while( c < '' || c > '' ) {
if( c == '-' ) f = - ;
c = getchar() ;
}
while( c >= '' && c <= '' ) {
x = (x << ) + (x << ) + c - ;
c = getchar() ;
}
return x * f ;
}
#undef I_int using namespace std ; #define N 1000100 struct node {
int len ;
char ch[ ] ;
} a[ N ] ;
int n , m , f[ N ] ;
char s[ N ] , ch[ N ] ; int main() {
scanf( "%s" , ch+ ) ;
while( ch[ ] != '.' ) {
a[ ++ n ].len = strlen( ch+ ) ;
for( int i = , len = strlen( ch+ ) ; i <= len ; i ++ ) {
a[ n ].ch[ i ] = ch[ i ] ;
}
scanf( "%s" , ch+ ) ;
}
int m = ;
while( scanf( "%s" , ch+ ) == ) {
int len = strlen( ch+ ) ;
for( int i = ; i <= len ; i ++ ) {
s[ i + m ] = ch[ i ] ;
}
m += len ;
}
f[ ] = ;
for( int i = ; i <= m ; i ++ ) {
for( int j = ; j <= n ; j ++ ) {
if( i + a[ j ].len <= m && f[ i ] ) {
bool flag = ;
for( int k = i + ; k <= a[ j ].len + i ; k ++ ) {
if( s[ k ] != a[ j ].ch[ k - i ] ) { flag = ; break ; }
}
if( flag ) continue ;
f[ i + a[ j ].len ] = ;
}
}
}
for( int i = m ; i >= ; i -- ) {
if( f[ i ] ) return outn( i ) , ;
}
}

奶牛家谱 Cow Pedigrees

关于这道题,做法很多..

我写了一个比较麻烦的做法,复杂度也很低$O(n^4)$

$f[i][j][k]$表示前$i$层放了$j$个节点,下一层要放$k$个节点的最优解

转移的方案可以利用组合数来算下一层能放的不同方案

但是不知道为什么我推杨辉三角出锅,于是使用了一下题解对组合数的求法。其实就是用组合数的另一个公式来推)

采用这种方法的话完全可以删掉C数组。我只是懒得删....

转移懒得再打一遍了。详见代码

#include <bits/stdc++.h>

using namespace std ;

#define N 510
#define mod 9901 int c[ N ][ N ] ;
int n , m ;
int f[ N ][ N ][ N ] ;
//前i层,前j个节点,这层放了k个节点 int power( int a , int b ) {
int ans = , base = a ;
while( b ) {
if( b& ) ans = ans * base % mod ;
base = base * base % mod ;
b >>= ;
}
return ans % mod ;
} int fac[N],ifac[N]; int main() {
scanf( "%d%d" , &n , &m ) ; fac[]=;
for( int i = ; i <= ; i ++ ) fac[i]=fac[i-]*i%mod;
for( int i = ; i <= ; i ++ ) ifac[ i ] = power( fac[ i ] , mod - ) % mod ;
for( int i = ; i <= ; i ++ )
for( int j = i ; j <= ; j ++ )
c[ i ][ j ] = fac[ j ] * ifac[ i ] % mod * ifac[ j - i ] % mod ; f[][][]=; f[][][]=;
for( int t = ; t <= m- ; t ++ ) {
for( int i = ; i < n ; i += ) { //当前层节点数
for( int j = (t<<1ll)- ; j < n ; j += ) { // 总点数
for( int k = ; k <= (i<<1ll) ; k+= ) { // 下一层放l个点
if( j + k > n ) break ;
f[t+][j+k][k]=(f[t+][j+k][k]+f[t][j][i]*c[k/][i]%mod)%mod;
}
}
}
} int ans = ;
for( int i = ; i <= ; i += )
ans = ( ans + f[ m ][ n ][ i ] ) % mod ;
printf( "%d\n" , ans ) ;
}

[USACO5.3]校园网Network of Schools

忽然写到这题就想起来我这坑弃了好久...

补一下坑

把图缩成个有向无环图之后,对于第一问显然只需要给0入度的点提供。然后第二问求要加多少条边这个缩点后的图能变成一个环,其实就是0出度和0入度取个max。注意对于缩点完后只有1个点的情况,第二问的答案是0

#include <cstring>
#include <algorithm>
#include <cstdio> #define ll long long
#define inf 0x3f3f3f3f
#define il inline namespace io { #define in(a) a=read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n') #define I_int int
inline I_int read() {
I_int x = , f = ; char c = getchar() ;
while( c < '' || c > '' ) { if( c == '-' ) f = - ; c = getchar() ; }
while( c >= '' && c <= '' ) { x = x * + c - '' ; c = getchar() ; }
return x * f ;
}
char F[ ] ;
inline void write( I_int x ) {
if( x == ) { putchar( '' ) ; return ; }
I_int tmp = x > ? x : -x ;
if( x < ) putchar( '-' ) ;
int cnt = ;
while( tmp > ) {
F[ cnt ++ ] = tmp % + '' ;
tmp /= ;
}
while( cnt > ) putchar( F[ -- cnt ] ) ;
}
#undef I_int }
using namespace io ; using namespace std ; #define N 100010 int n , in[N] , out[N] ;
int head[N] , cnt ;
struct edge {
int to , nxt;
} e[N<<];
int dfn[N] , low[N] , vis[N] , st[N] , bl[N] , tim , num , top; void ins(int u , int v) {
e[++cnt] = (edge) {v , head[u]} ;
head[u] = cnt ;
} void tarjan(int u) {
dfn[u] = low[u] = ++ tim ;
vis[u] = ; st[++top] = u ;
for(int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].to ;
if(!dfn[v]) {
tarjan(v) ;
low[u] = std::min(low[u] , low[v]) ;
} else if(vis[v]) low[u] = std::min(low[u] , dfn[v]) ;
}
if(dfn[u] == low[u]) {
int x ; num ++ ;
do {
x = st[top --] ;
vis[x] = ;
bl[x] = num ;
}while(x != u) ;
}
} int main() {
n = read() ;
for(int i = ; i <= n ; i ++) {
int x = read() ;
while(x != ) {
ins(i , x) ;
x = read() ;
}
}
for(int i = ; i <= n ; i ++) {
if(!dfn[i]) tarjan(i) ;
}
for(int u = ; u <= n ; u ++) {
for(int i = head[u] ; i ; i = e[i].nxt) {
int v = e[i].to ;
if(bl[u] != bl[v]) in[bl[v]] ++ , out[bl[u]] ++ ;
}
}
int ans1 = , ans2 = ;
for(int i = ; i <= num ; i ++) {
if(!in[i]) ans1 ++ ;
if(!out[i]) ans2 ++ ;
}
if(num == ) outn() , outn() ;
else outn(ans1) , outn(std::max(ans1 , ans2)) ;
return ;
}

Luogu USACO Training 刷水记录的更多相关文章

  1. USACO Training刷题记录 By cellur925

    Section 1.1 Your Ride Is Here 貌似没啥可说 Greedy Gift Givers 上来就想stl map映射,有两个坑:如果送给别人的人数为0,那么需要特判一下,防止整数 ...

  2. Codeforces 刷水记录

    Codeforces-566F 题目大意:给出一个有序数列a,这个数列中每两个数,如果满足一个数能整除另一个数,则这两个数中间是有一条边的,现在有这样的图,求最大联通子图. 题解:并不需要把图搞出来, ...

  3. [暑假的bzoj刷水记录]

    (这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊  堆一起算了 隔一段更新一下.  7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...

  4. usaco silver刷水~其实是回顾一下,补题解

    [BZOJ1606][Usaco2008 Dec]Hay For Sale 裸01背包 ;i<=n;i++) for(int j=m;j>=a[i];j--) f[j]=max(f[j], ...

  5. 【COGS & USACO Training】710. 命名那个数字(hash+水题+dfs)

    http://cojs.tk/cogs/problem/problem.php?pid=710 近日开始刷水... 此题我为了练一下hash...但是hash跑得比暴力还慢.. 不言而喻... #in ...

  6. 2021.12.16 eleveni的刷题记录

    2021.12.16 eleveni的刷题记录 1. 数论 https://www.luogu.com.cn/problem/P2532 1.1卡特兰数 https://www.luogu.com.c ...

  7. 关于USACO Training

    做了这么久的题目,突然发现最经典的 USACO Training 还没有做过?加速水一遍吧!我会把题解放在上面的.

  8. USACO Training Section 1.1 坏掉的项链Broken Necklace

    题目描述 你有一条由N个红色的,白色的,或蓝色的珠子组成的项链(3<=N<=350),珠子是随意安排的. 这里是 n=29 的二个例子: 第一和第二个珠子在图片中已经被作记号. 图片 A ...

  9. 2021.12.21 eleveni的刷题记录

    2021.12.21 eleveni的刷题记录 0. 有意思的题 P6701 [POI1997] Genotype https://www.luogu.com.cn/problem/P6701 状压优 ...

随机推荐

  1. (3.11)mysql基础深入——mysql文件分类与配置文件管理

    (3.11)mysql基础深入——mysql文件分类与管理 关键词:mysql配置文件,mysql参数文件,mysql中的my.cnf 目录:mysql数据库文件分类: [1]参数文件:my.cnf ...

  2. FineReport实现java报表权限使用的效果图

    Java报表-多级权限配置说明 Java报表-联合填报 Java报表-模板内容权限控制 Java报表-权限细粒度控制

  3. 迁移到 Linux :入门介绍 | Linux 中国

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79001952 这个新文章系列将帮你从其 ...

  4. vue学习七之Axios

    JQuery时代,我们使用ajax向后台提交数据请求,Vue时代,Axios提供了前端对后台数据请求的各种方式. 什么是Axios Axios是基于Promise的Http客户端,可以在浏览器和nod ...

  5. Android adb.exe程序启动不起来处理方法

    经常遇到 Please ensure that adb is correctly located at 'D:\java\sdk\platform-tools\adb.exe' and can be ...

  6. Catch all the latest Jordan Release Dates

    In case y'all missed yesterday's news, Air Jordan 13 Olive 2018 officially unveiled their 2017 Holid ...

  7. Java有序数组的实现

    package 有序数组; public class OrdArray { private long[]array; private int nElems; //初始化 public OrdArray ...

  8. Django初级手册2-管理界面的使用及定制

    管理界面的使用 管理界面的URL,帐号和密码在第一次输入syncdb时建立 http://127.0.0.1:8000/admin/ 将app加入管理界面 编辑polls/admin.py from ...

  9. bootstrap 带有确定取消按钮的modal

    </div><div class="modal fade" id="confirmModal" tabindex="-1" ...

  10. mysql5.7服务器The innodb_system data file 'ibdata1' must be writable导致无法启动服务器

    现象如下:The innodb_system data file 'ibdata1' must be writable. 解决方案如下: 1.关闭mysqld进程: 2.删除配置文件中datadir所 ...