BUPT 2019 summer training Milkshake Party

A - 森林口味的奶昔 (CF285C)

注意到這是森林,所以必然有葉子結點。我們可以根據葉子結點拓撲排序順便異或就是答案。

#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int N =  (1<<17), M = N << 3;
// struct edge {
//     int nx,to;
// } e[M];
// int head[N], mal=1;
int xx[M], yy[M], mal=0;
void addedge(int u, int v) {
    xx[++mal]=u;yy[mal]=v;
    //e[mal].to = v; e[mal].nx = head[u]; head[u] = mal++;
}

void init() {
    mal = 0;
    //memset(head, 0, sizeof(head));
}

int a[N], b[N];
queue<int> Q;
signed main() {
    int n;
    scanf("%d",&n);
    
    for(int i =0; i<n;i++){
        scanf("%d%d",&a[i], &b[i]);
    }

    for(int i = 0;i<n;i++) {
        if (a[i] == 1) {
            Q.push(i);
        }
    }
    while(Q.size()) {
        int tmp = Q.front();Q.pop();
        if (a[tmp]==0){
            continue;
        }
        if (--a[b[tmp]] ==1){
            Q.push(b[tmp]);
        }
        addedge(tmp, b[tmp]);
        a[tmp] = 0;
        b[b[tmp]]^=tmp;
    }
    printf("%d\n",mal);
    for(int i =1;i<=mal;i++) {
        printf("%d %d\n",xx[i],yy[i]);
    }
}

B - 食堂口味的奶昔 (HDU2546)

異種揹包,注意這裏的dp開到了3000,值域爲[-1500,1499]。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int DP[3000],*dp=DP+1500;
int a[2000];
int main(){
    int n,m,mi;
    while(scanf("%d",&n),n){
        memset(DP,0,sizeof(DP));
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
        scanf("%d",&m);
        mi=m;
        dp[m]=1;
        for(int j=1;j<=n;j++){
            for(int i=5;i<=m;i++){
                if(dp[i]){
                    dp[i-a[j]]=1;
                    if(i-a[j]<mi)mi=i-a[j];
                }
            }
        }
        printf("%d\n",mi);
    }
}

C 黑暗料理奶昔 (CF526B)

根據路徑倒着做一遍即可,統計答案順便把子路徑權值加到對應邊上。

#include <cstdio>
#include <algorithm>
using namespace std;
int a[1<<13],b[1<<13];
int main() {
    int nn;
    scanf("%d",&nn);
    int n = (1<<(nn+1))-1;
    for(int i =2;i<=n;i++){
        scanf("%d",&a[i]);
    }
    int ret=0;
    for(int i = n;i>=1;i--){
        a[i] +=max(a[i<<1],a[i<<1|1]);
        ret+=max(a[i<<1|1],a[i<<1]) - min(a[i<<1|1],a[i<<1]);
    }
    printf("%d\n",ret);
}

D - ABC奶昔 (CF624C)

首先可以確定的是,如果第i個位置存在於它不同的點,那麼它一定可以做到唯一確認一種染色(否則輸出No),所以相當於試圖構造多個二分圖。其次,如果第i個位置和周圍所有的點都相鄰,那麼它一定可以塗成'b'。這樣就覆蓋了所有的情況。構造完了以後,再倒回來看染色是否正確,如果不正確就輸出No。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <bitset>
using namespace std;

bitset<505> E[505],En[505];
char setting[505];
    int n,m;
bool dfs(int i) {
    for(int j=1;j<=n;j++) {
        if (En[i][j]) {
            if (setting[j]!=0) {
                if (setting[j] == setting[i]){
                    return false;
                }
                continue;
            }
            setting[j]=(setting[i]=='a'?'c':'a');
            if(!dfs(j)) {
                return false;
            }
        }
    }
    return true;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i =1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        E[a][b]=1;E[b][a]=1;
    }
    for(int i =1;i<=n;i++){
        En[i] = ~E[i];
        En[i][i]=0;
        setting[i]=0;
        // cout << En[i] << endl;
    }
    for(int i =1;i<=n;i++){
        if((E[i].count()!=((unsigned long long)n-1)) && setting[i]==0 && ![&]() -> bool {
            // printf("%d",);
            setting[i]='a';
            return dfs(i);
        }()){
            puts("No");
            return 0;
        }
    }
    for(int i=1;i<=n;i++) {
        if (setting[i]==0) {
            setting[i]='b';
        }
    }
    for(int i =1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(E[i][j] && abs(setting[i] - setting[j])>=2){
                puts("No");
                return 0;
            }
        }
    }
    puts("Yes");
    setting[n+1]=0;
    puts(setting+1);
}

E - Link-Cut-Tree上的奶昔 (CF614A)

暴力做即可,爲了防爆long long,我使用了long double的神祕魔法,當然double也可以。

#include <cstdio>
bool check(long long rr, long long mul) {
    if((long double)(rr) * mul > 1e18) {
        return false;
    }
    return true;
}
int main() {
    long long l,r,n;
    scanf("%lld%lld%lld",&l,&r,&n);
    long long rr=1,fl=0;
    if(l<=rr && rr<=r){
        printf("%lld ",rr);
        fl=1;
    }
    while(check(rr,n)) {
        rr *=n;
        if(l<=rr &&rr <=r) {
        printf("%lld ",rr);
        fl=1;
        }
    }
    if(!fl){
        printf("-1\n");
    }
}

F - 原味奶昔 (CF296A)

歐幾里得變種題,簡單…

#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
    long long  n,m;
    scanf("%lld%lld",&n,&m);
    if(n < m)swap(n,m);
    long long r, ret=0;
    while(m) {
        ret+=n/m;
        r = n % m;
        n = m;
        m = r;
    }
    printf("%lld\n",ret);
}

G - 珍珠奶茶 (CF2B)

祖傳題,考慮免死金牌0的情況並做兩遍取最小值。

#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=1500005;
int _2[1005][1005]={0},_5[1005][1005]={0};
int res=0,dp[1005][1005]={0},dp5[1005][1005]={0},
last[1005][1005],last5[1005][1005];
const int mod=1024;
void print(int x,int y,int ls[][1005]){
	if(x==1&&y==1)return ;
	int xx=ls[x][y]>>10,yy=ls[x][y]%1024;
	print(xx,yy,ls);
	printf("%s",(xx+1==x)?"D":"R");
}
int main(){
	int n,flag=0,a,x,y;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a);
			if(!a){
				flag=1;_2[i][j]=INF;_5[i][j]=INF;x=i;y=j;
			}else {
				while(a%2==0)a/=2,_2[i][j]++;
				while(a%5==0)a/=5,_5[i][j]++;
				//printf("%d,%d %d\n",i,j,_2[i][j]);
			}
		}
	}
	for(int i=2;i<=n;i++)dp[i][0]=dp[0][i]=dp5[0][i]=dp5[i][0]=INF;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(dp[i-1][j]<dp[i][j-1]){
				last[i][j]=((i-1)<<10)+j;
				dp[i][j]=dp[i-1][j]+_2[i][j];
			}else{
				last[i][j]=(i<<10)+j-1;
				dp[i][j]=dp[i][j-1]+_2[i][j];
			}
			if(dp5[i-1][j]<dp5[i][j-1]){
				last5[i][j]=((i-1)<<10)+j;
				dp5[i][j]=dp5[i-1][j]+_5[i][j];
			}else{
				last5[i][j]=(i<<10)+j-1;
				dp5[i][j]=dp5[i][j-1]+_5[i][j];
			}
		}
	}
	//printf("%d %d\n",dp[n][n],dp5[n][n]);
	res=min(dp[n][n],dp5[n][n]);
	if(res>=1&&flag){
		printf("%d\n",1);
		for(int i=1;i<x;i++)printf("D");
		for(int i=1;i<y;i++)printf("R");
		for(int i=x;i<n;i++)printf("D");
		for(int i=y;i<n;i++)printf("R");
	}else{
		printf("%d\n",res);
		if(dp[n][n]<dp5[n][n])print(n,n,last);
		else print(n,n,last5);
	}
}
/*
2
10 2
5 2
 */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章