2015 ICPC 长春

A - Too Rich

给定每一种面值的硬币的个数,求出用最多硬币表示出所给价值。
倒着做可以用前缀和优化和剪枝。
可以$O(1)$算出当前面值减去前缀和之后最少需要几个,然后在此基础上多做3次就可以了,因为前一种硬币最多3枚就可以表示后一种硬币了。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int dx[] = {1, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 2000};

int a[20];
int T, p;
ll S[20];
int ans;

inline void upd(int &x, int y) {
	if (y > x) x = y;
}

void dfs(int dep, ll val, int coins) {
	//printf("%d %d %d
", dep, val, coins);
	if (val < 0) {
		return;
	}
	if (val == 0) {
		upd(ans, coins);
		return;
	}
	if (dep == 0) {
		return;
	}
	int left = val - S[dep - 1];
	if (left <= 0) {
		dfs(dep - 1, val, coins);
		if (a[dep] >= 1)
			dfs(dep - 1, val - dx[dep], coins + 1);
	} else {
		int i = left / dx[dep];
		if (left % dx[dep]) i++;
		if (i <= a[dep])
			dfs(dep - 1, val - i * dx[dep], coins + i);
		else
			dfs(dep - 1, val - a[dep]*dx[dep], coins + i);
		i++;
		if (i <= a[dep])
			dfs(dep - 1, val - i * dx[dep], coins + i);
		i++;
		if (i <= a[dep])
			dfs(dep - 1, val - i * dx[dep], coins + i);
	}

}
int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &p);
		for (int i = 1; i <= 10; i++)
			scanf("%d", &a[i]);
		for (int i = 1; i <= 10; i++)
			S[i] = S[i - 1] + (ll)(a[i] * dx[i]);
		ans = -1;
		dfs(10, (ll)p, 0);
		cout << ans << endl;
	}
	return 0;
}

B - Count a * b

猜了一发结论$sum_{i|n} i^2 - sum_{i|n} 1$,结果是tle,卡了$O(Tsqrt(n))$的做法,加了枚举的优化。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

const int N = 1e5;

bool p[100005];
int prime[100005],top;

struct node{
	int x,y;
}ort[10005];

void init(){
	memset(p, 0, sizeof(p));
	top = 0;
	for (int i = 2; i <= N; ++i) {
		if (!p[i]) {
			prime[++top] = i;
		}
		for (int j = 1; j <= top; ++j) {
			if (i * prime[j] > N)
				break;
			p[i * prime[j]] = 1;
			if (i % prime[j] == 0)
				break;
		}
	}
}

ull r1,r2;
int ctop;

void dfs(int dep,int now){
	if(dep==ctop+1){
		r1+=(ull)now*now;
		return;
	}
	int t=1;
	for(int i=0;i<=ort[dep].y;i++){
		dfs(dep+1,now*t);
		t*=ort[dep].x;
	}
}

int main() {
	//freopen("in.txt","r",stdin);
	init();
	int n, T;
	cin >> T;
	while (T--) {
		scanf("%d", &n);
		int tmp=n;
		// ull res1 = 0, res2 = 0;
		// for (int i = 1; i * i <= n; i++) {
		// 	if (n % i == 0) {
		// 		res1 += (ull)i * i;
		// 		res2 ++;
		// 		if (i * i != n) {
		// 			int t = n / i;
		// 			res1 += (ull)t * t;
		// 			res2 ++;
		// 		}
		// 	}
		// }
		// res1 -= (ull)n * res2;
		// printf("%llu
", res1);
		ctop=0;
		for(int i=1;i<=top && prime[i]*prime[i]<=n;i++){
			if(n%prime[i]==0){
				ctop++;
				ort[ctop].x=prime[i];
				ort[ctop].y=0;
				while(n%prime[i]==0){
					ort[ctop].y++;
					n/=prime[i];
				}
			}
		}
		if(n!=1){
			ctop++;
			ort[ctop].x=n;
			ort[ctop].y=1;
		}
		r1=0;r2=1;
		for(int i=1;i<=ctop;i++)
			r2=r2*(ull)(ort[i].y+1);
		r2=r2*(ull)tmp;
		dfs(1,1);
		cout<<r1-r2<<endl;
	}
	return 0;
}

F - Almost Sorted Array

判断是不是almost sorted array。
跟着跑LIS,如果栈高比当前i小太多直接就是不对的了。
所以复杂度还是$O(n)$。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int T, n, k, a[maxn], k1, k2, ans[maxn], len, b[maxn], flag;
template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}
int main() {
	//freopen("in.txt", "r", stdin);
	read(T);
	while (T--) {
		flag = 0;
		memset(ans, 0, sizeof(ans));
		k1 = k2 = 0;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			read(a[i]);
		ans[1] = a[1];
		len = 1;
		for (int i = 2; i <= n; i++) {
			if (a[i] >= ans[len])
				ans[++len] = a[i];
			else {
				int pos = upper_bound(ans + 1, ans + len + 1, a[i]) - ans;
				ans[pos] = a[i];
			}
			if(i-len>5) break;
		}
		if (len >= n - 1) {
			puts("YES");
			continue;
		}
		for (int i = 1; i <= n; i++)
			b[i] = a[n - i + 1];
		ans[1] = b[1];
		len = 1;
		for (int i = 2; i <= n; i++) {
			if (b[i] >= ans[len])
				ans[++len] = b[i];
			else {
				int pos = upper_bound(ans + 1, ans + len + 1, b[i]) - ans;
				ans[pos] = b[i];
			}
			if(i-len>5) break;
		}
		if (len >= n - 1) puts("YES");
		else puts("NO");
	}
	return 0;
}

G - Dancing Stars on Me

每个点只有两个最近点,并且最近的距离相等。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

double eps = 1e-8;

inline int dcmp(double x) {
	if (x > eps) return 1;
	if (x < -eps) return -1;
	return 0;
}

struct node {
	int x, y;
} info[1005];

int cnt[1005];

double getdist(int i, int j) {
	double rx = info[i].x - info[j].x;
	double ry = info[i].y - info[j].y;
	double ret = rx * rx + ry * ry;
	return ret;
}

int main() {
	//freopen("in.txt","r",stdin);
	int T,n;
	cin >> T;
	while (T--) {
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d%d", &info[i].x, &info[i].y);
		double cmp = 1e15;
		for (int i = 2; i <= n; i++) {
			cmp = min(cmp, getdist(1, i));
		}
		bool flag=1;
		memset(cnt,0,sizeof cnt);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i==j) continue;
				if(dcmp(getdist(i,j)-cmp)==0) cnt[i]++;
				if(dcmp(getdist(i,j)-cmp)<0){
					flag=0;
					break;
				}
			}
		}
		for(int i=1;i<=n;i++)
			if(cnt[i]!=2){
				flag=0;
				break;
			}
		puts(flag?"YES":"NO");
	}
	return 0;
}

H - Partial Tree

2n-2个度分配给n个点。
原本是一个二维消费的背包。
有一个特殊的条件就是每个点至少一个度,那么可以直接先把这些度分配给n个点。
然后就是n-2个度任意分配的背包问题,把得到的价值修改成a[i+1]-a[1]就行了。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

int f[10005];
int dp[4400],res;

int main() {
	//freopen("in.txt","r",stdin);
	int T,n;
	cin >> T;
	while (T--) {
		scanf("%d",&n);
		for(int i=1;i<n;i++)
			scanf("%d",&f[i]);
		res = (ll)f[1]*n;
		//cout<<res<<endl;
		for(int i=2;i<n;i++)
			f[i]-=f[1];
		for(int i=0;i<n;i++)
			dp[i]=-INT_MAX;
		dp[0]=0;
		for(int i=1;i<n-1;i++)
			for(int j=i;j<=n-2;j++){
				dp[j]=max(dp[j],dp[j-i]+f[i+1]);
			}
		// for(int i=1;i<=n-2;i++)
		// 	printf("%d ",dp[i]);
		// puts("");
		cout<<dp[n-2]+res<<endl;
	}
	return 0;
}

J - Chip Factory

居然可以暴力过。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

template<typename T> inline void read(T &x) {
	x = 0; T f = 1; char ch; do {ch = getchar(); if (ch == '-')f = -1;} while (ch < '0' || ch > '9'); do x = x * 10 + ch - '0', ch = getchar(); while (ch <= '9' && ch >= '0'); x *= f;
}

template<typename A, typename B> inline void read(A&x, B&y) {read(x); read(y);}
template<typename A, typename B, typename C> inline void read(A&x, B&y, C&z) {read(x); read(y); read(z);}
template<typename A, typename B, typename C, typename D> inline void read(A&x, B&y, C&z, D&w) {read(x); read(y); read(z); read(w);}

int a[1005];

int main() {
	//freopen("in.txt","r",stdin);
	int T, n;
	read(T);
	while (T--) {
		read(n);
		for (int i = 1; i <= n; i++)
			read(a[i]);
		int Mx = 0;
		for (int i = 1; i < n; i++)
			for (int j = i + 1; j < n; j++)
				for (int k = j + 1; k <= n; k++) {
					Mx = max(Mx, (a[i] + a[j])^a[k]);
					Mx = max(Mx, (a[i] + a[k])^a[j]);
					Mx = max(Mx, (a[k] + a[j])^a[i]);
				}
		printf("%d
",Mx);
	}
	return 0;
}

然后$O(n^2 log n)$,枚举$S_i$,$S_j$从字典树删除,贪心查询$S_k$。

#include <bits/stdc++.h>

using namespace std;
const int maxn = 10000+5;
typedef long long ll;
ll bin[35];
int n,m;
ll a[maxn],x;

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}
template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}

struct trie{
    int cnt;
    int ch[maxn*35][2];
    ll val[maxn*35];
    int ts[maxn*35];
    inline void init(){
        cnt=1;
        memset(ch[0],0,sizeof ch[0]);
        ts[0]=0;
        //memset(ts,0,sizeof ts);
    }
    inline void insert(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            if(!ch[u][t]){
                memset(ch[cnt],0,sizeof ch[cnt]);
                val[cnt]=0;
                ts[cnt]=0;
                ch[u][t]=cnt++;
            }
            u=ch[u][t];
            ts[u]++;
        }
        val[u]=a;
    }
    inline void del(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            u=ch[u][t];
            ts[u]--;
        }
    }
    inline ll query(ll a){
        int u=0;
        for(int i=32;i>=0;i--){
            ll t=a&bin[i];t>>=i;
            if(ch[u][t^1]&&ts[ch[u][t^1]]) u=ch[u][t^1];
            else u=ch[u][t];
        }
        return val[u]^a;
    }
}Trie;

int main(){
    //freopen("in.txt","r",stdin);
    bin[0]=1;for(ll i=1;i<=35;i++) bin[i]=bin[i-1]*2ll;
    int T,cas=1;
    for(cin>>T,cas=1;cas<=T;cas++){
        scanf("%d",&n);
        Trie.init();
        for(int i=1;i<=n;i++){
            read(a[i]);
            Trie.insert(a[i]);
        }
        ll mx=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
                Trie.del(a[i]);Trie.del(a[j]);
                mx=max(mx,Trie.query(a[i]+a[j]));
                Trie.insert(a[i]);Trie.insert(a[j]);
            }
        printf("%lld
",mx);
    }
    return 0;
}

L - House Building

#include <bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define per(i,x,y) for(int i=x;i>=y;i--)
#define debug(a) cerr<<#a<<"=="<<a<<endl
#define iout(x) printf("%d
",x)
#define lout(x) printf("%lld
",x)
#define iin(x) scanf("%d",&x)
#define lin(x) scanf("%lld",&x)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int, int> PII;
const int mod=1e9+7;
template<typename T> inline void read (T &x) {
    x = 0; T f = 1;
    char ch;
    do {
        ch = getchar(); if (ch == '-') f = -1;
    } while (ch < '0' || ch > '9');
    do x = x * 10 + ch - '0', ch = getchar();
    while (ch <= '9' && ch >= '0'); x *= f;
}

template<typename A, typename B> inline void read (A &x, B &y) {read (x);read (y);}
template<typename A, typename B, typename C> inline void read (A &x, B &y, C &z) {read (x);read (y);read (z);}
template<typename A, typename B, typename C, typename D> inline void read (A &x, B &y, C &z, D &w) {read (x);read (y);read (z);read (w);}
template<typename A,typename B> inline A fexp(A x,B p){A ans=1;for(;p;p>>=1,x=1LL*x*x%mod)if(p&1)ans=1LL*ans*x%mod;return ans;}
template<typename A,typename B> inline A fexp(A x,B p,A mo){A ans=1;for(;p;p>>=1,x=1LL*x*x%mo)if(p&1)ans=1LL*ans*x%mo;return ans;}
//head
int t;
int a[100][100];
int n,m;
int main() {
	//freopen("in.txt","r",stdin);
	read(t);

	while(t--) {
		memset(a,0,sizeof(a));
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++) {

			for(int j=1;j<=m;j++) {
				scanf("%d",&a[i][j]);
			}
		}
		int ans=0;
		rep(i,1,n) {
			rep(j,1,m) {
				if(a[i][j]!=0) ans++;
				if(a[i][j]>a[i-1][j]) ans+=a[i][j]-a[i-1][j];
				if(a[i][j]>a[i+1][j]) ans+=a[i][j]-a[i+1][j];
				if(a[i][j]>a[i][j-1]) ans+=a[i][j]-a[i][j-1];
				if(a[i][j]>a[i][j+1]) ans+=a[i][j]-a[i][j+1];
			}
		}
		printf("%d
",ans);
	}

	return 0;
}
原文地址:https://www.cnblogs.com/foreignbill/p/7875735.html