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
*/