A.相似颜色
每两位枚举一下0~15,更新一下就好了。。
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,a,b) for(int i=(a);i<=(b);i++)
#define DOWN(i,a,b) for(int i=(a);i>=(b);i--)
#define CLR(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const ll LL_INf=0x3f3f3f3f3f3f3f3f;
const int N=100000+10;
const int mod=1e8+7;
int tran(char c){
if ('0'<=c&&c<='9') return c-'0';
else return c-'a'+10;
}
int encode(char a,char b){
return 16*tran(a)+tran(b);
}
char decode(int a){
if (a>=0&&a<=9) return a+'0';
else return a-10+'a';
}
string s;
int num[3];
int main(){
cin>>s;
cout<<'#';
num[0]=encode(s[1],s[2]);
num[1]=encode(s[3],s[4]);
num[2]=encode(s[5],s[6]);
// FOR(i,0,3) cout<<num[i]<<' '<<endl;
FOR(i,0,3){
int big=INF;
int k;
for(int j=0;j<=15;j++){
int tmp=16*j+j;
if ((tmp-num[i])*(tmp-num[i])<big){
big=(tmp-num[i])*(tmp-num[i]);
k=tmp;
}
}
// cout<<"k="<<k<<endl;
cout<<decode(k%16);
}
}
B.挑选子集
如果知道剩余系的概念,这题应该就秒了。。
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,a,b) for(int i=(a);i<=(b);i++)
#define DOWN(i,a,b) for(int i=(a);i>=(b);i--)
#define CLR(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const ll LL_INf=0x3f3f3f3f3f3f3f3f;
const ll mod=1000000009;
const int N=1000+10;
int n,m,k,num;
ll c[N][N],a[N],b[N],ans;
int main(){
c[0][0]=1;
REP(i,1,100){
c[i][0]=1;
REP(j,1,i){
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
}
cin>>n>>m>>k;
FOR(i,0,n) cin>>b[i];
// n=unique(b,b+n)-b;
FOR(i,0,n) {
a[b[i]%k]++;
}
REP(i,0,k-1) ans=(ans+c[ a[i] ][m])%mod;
cout<<ans<<endl;
}
C.矩阵迷宫
动态规划,用dp[i][j][k][0]和dp[i][j][k][1]表示,到(i,j)格改变了k次移动方向分别方向为向右和向下时所需支付的最小代价
唯一的坑点就是,由于2的幂很大,所以k不能枚举到n,也并不需要枚举到n,枚举20就差不多了,因为可以保证,只用改变一次方向并且只用200*100代价就能到终点。。很多人因为这个只有30分
#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,a,b) for(int i=(a);i<=(b);i++)
#define DOWN(i,a,b) for(int i=(a);i>=(b);i--)
#define CLR(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const ll LL_INF=0x3f3f3f3f3f3f3f3f;
const int mod=1e8+7;
const int N=100+10;
ll dp[N][N][N][2];
int n,a[N][N];
ll ans;
int main(){
cin>>n;
REP(i,1,n){
REP(j,1,n){
cin>>a[i][j];
}
}
memset(dp,0x3f,sizeof(dp));
dp[1][1][0][0]=a[1][1];
dp[1][1][0][1]=a[1][1];
REP(i,1,n){
REP(j,1,n){
if (i==1&&j==1) continue;
REP(k,0,15){
dp[i][j][k][0]=min(dp[i][j-1][k][0]+a[i][j],dp[i][j][k][0]);
if (k) dp[i][j][k][0]=min(dp[i-1][j][k-1][1]+(1<<k-1)+a[i][j],dp[i][j][k][0]);
dp[i][j][k][1]=min(dp[i-1][j][k][1]+a[i][j],dp[i][j][k][1]);
if (k) dp[i][j][k][1]=min(dp[i][j-1][k-1][0]+(1<<k-1)+a[i][j],dp[i][j][k][1]);
}
}
}
// REP(k,0,2*n){
// REP(i,1,n){
// REP(j,1,n){
// cout<<dp[i][j][k][0]<<'/'<<dp[i][j][k][1]<<' ';
// }
// cout<<endl;
// }
// cout<<endl;
// }
ans=LL_INF;
REP(k,0,15){
REP(i,0,1){
ans=min(ans,dp[n][n][k][i]);
}
}
cout<<ans<<endl;
return 0;
}
D.第K小先序遍历
比赛时,由于放在第四题,很多人(我)以为很难,其实并不是很难。。这题有Catalan的背景,给出一个n个点的二叉树的中序遍历,求有多少颗不相同的树,答案就是Catalan树,知道这个之后,感觉一下,先对元素大小排序,通过k,知道第一个数是哪一位,然后不断分成两棵树,分治下去就好了。。
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define CLR(a) memset(a,0,sizeof(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,a,b) for(int i=(a);i<=(b);i++)
#define DOWN(i,a,b) for(int i=(a);i>=(b);i--)
#define DBG(x) cout<<"x"<<'='<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const ll LL_INf=0x3f3f3f3f3f3f3f3f;
const ll mod=1000000009;
const int N=30+10;
int n,k,a[N];
vector<int> ans;
ll T[N];
void solve(int l,int r,ll k){
// cout<<"l="<<l<<" r="<<r<<" k="<<k<<endl;
if (l>r) return;
vector< pair<int,ll> > p;
REP(i,l,r) p.push_back( make_pair(a[i],i) );
sort(p.begin(),p.end());
// FOR(i,0,p.size()) cout<<p[i].second<<' ';
// cout<<endl;
int pos;
FOR(i,0,p.size()){
pos=p[i].second;
ll num=T[pos-l]*T[r-pos];
if (k-num<=0) {
ans.push_back(p[i].first);
break;
}
k-=num;
}
ll k1=(k-1)/T[r-pos]+1;
ll k2=(k-1)%T[r-pos]+1;
solve(l,pos-1,k1);
solve(pos+1,r,k2);
}
int main(){
cin>>n>>k;
REP(i,1,n) cin>>a[i];
T[0]=T[1]=1;
REP(i,2,n){
REP(j,0,i-1){
T[i]+=T[j]*T[i-1-j];
}
}
solve(1,n,k);
FOR(i,0,n) cout<<ans[i]<<endl;
return 0;
}