第九届河南理工大学算法程序设计大赛

一边监考一边写了几个题。一队出的题目挺好的。总的来说,题目不难,但是坑点比较多,细心点才能做好。

A. Asia区域赛

签到题:

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;


int main(){
	cout << 29+58+87+13 << endl;
	return 0;
}

B. Asia区域制

二进制转换十进制,注意数据的范围很大。所以先把二进制转化为long long 类型的10进制数再转化为16进制字符串是错误的。

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))

typedef long long ll;
const int maxn = 1e6 + 10;

void solve(string c){
	if(c == "0000") printf("0");
	else if(c == "0001")printf("1");
	else if(c == "0010")printf("2");
	else if(c == "0011")printf("3");
	else if(c == "0100")printf("4");
	else if(c == "0101")printf("5");
	else if(c == "0110")printf("6");
	else if(c == "0111")printf("7");
	else if(c == "1000")printf("8");
	else if(c == "1001")printf("9");
	else if(c == "1010")printf("a");
	else if(c == "1011")printf("b");
	else if(c == "1100")printf("c");
	else if(c == "1101")printf("d");
	else if(c == "1110")printf("e");
	else if(c == "1111")printf("f");
}

int main(){
	int t;
	scanf("%d", &t);
	getchar();
	while(t--){
		string s;
		cin >> s;
		int len = s.length();
		if(len % 4 == 1) s = "000" + s;
		else if(len % 4 == 2) s = "00" + s;
		else if(len % 4 == 3) s = "0" + s;
		len  = s.length();
		
		for(int i = 0; i < len; i+=4){
			string x;
			for(int j = 0; j < 4; j++){
				x += s[i+j];
			}
			solve(x);
		}
		printf("\n");
	}
	return 0;
}

C. Asia区域宫

表面上看是个BFS求最短路径,仔细看一下数据发现巨jb大,所以bfs 是不可行的。

观察题目:障碍物在迷宫中不能同行且不能同列。

所以。如果不能到达终点,图中只能是从左下到右上的墙。所以,标记每条斜线上的墙壁个数就好了。

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))

typedef long long ll;
const int maxn = 1e6 + 10;
const int N = 10001;

int n, m, x, y, t, a[N];

int main(){
	scanf("%d", &t);
	while(t--){
		bool flag = true;
		scanf("%d%d", &n, &m);
		for(int i = 0; i < m; i++){
			scanf("%d%d", &x, &y);
			int tes = x + y - 1;
			a[tes] ++;
			if(a[tes] >= tes) {
				flag = false;
			}
		}
		if(flag) printf("Yes %d\n", (n-1)*2);
		else printf("No\n");
		clr(a);
	}
	return 0;
}

D. Asia区域阵

待补

#pragma GCC optimize ("O3")
#pragma GCC optimize ("O2")
#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define met(s) memset(s, 0, sizeof(s))
#define rep(i, a, b) for(int i = a; i <= b; ++i)
template <class T> inline void scan_d(T &ret) {
char c; ret = 0;
while ((c = getchar()) < '0' || c > '9');
while (c >= '0' && c <= '9') { 
ret = ret * 10 + (c - '0'), c = getchar();}}
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int MAXN = 1e2 + 10;
char str[MAXN][MAXN];
int dp1[MAXN][MAXN], dp2[MAXN][MAXN], vis[30];

int main() {
//	freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
	int T;
	scanf("%d", &T);
	while(T--) {
		int n, m;
		scanf("%d %d", &n, &m);
		for(int i = 0; i < n; ++i) scanf("%s", str[i]);
		for(int i = 0; i < n; ++i) {
			for(int j = 0; j < m; ++j) {
				dp1[i][j] = dp2[i][j] = 0;
				memset(vis, 0, sizeof(vis));
				for(int p = 0; ;++p) {
					if(vis[str[i][j + p] - 'A'] || j + p >= m) break;
					vis[str[i][j + p] - 'A'] = 1;
					dp1[i][j]++;
				}
				memset(vis, 0, sizeof(vis));
				for(int p = 0; ;++p) {
					if(vis[str[i + p][j] - 'A'] || i + p >= n) break;
					vis[str[i + p][j] - 'A'] = 1;
					dp2[i][j]++;
				}
			//	printf("# %d -> %d %d\n", i, j, dp2[i][j]);
			}
		}
		int ans = 0;
		for(int i = 0; i < n; ++i) {
			for(int j = 0; j < m; ++j) {
				for(int k = 0; k < dp2[i][j]; ++k) {
					int cnt = INF;
					for(int p = 0; p <= k; ++p) {
						cnt = min(cnt, dp1[i + p][j]);
					}
					int res = k + 1;
					for(int p = 0; p < cnt; ++p) {
						res = min(res, dp2[i][j + p]);
					}
				//	printf("# %d %d\n", cnt, res);
					ans = max(ans, cnt * res);
				}
			}
		}
		printf("%d\n", ans);
	}
    return 0;
}

E. Mo的游戏

用一个数组标记一下上一次出现字符的位置,然后在遍历一遍选出最大的

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

char s[maxn];
int a[26], A[26];
int an[26], An[26];

int main(){
    scanf("%s", s);
    int len = strlen(s);
    for(int i = 0; i < 26; i++){
    	a[i] = -1; A[i] = -1;
    	an[i] = len; An[i] = len;
	}
    for(int i = 0; i < len; i++){
    	if(s[i] >= 'a' && s[i] <='z'){
    		if(a[s[i]-'a'] == -1) a[s[i]-'a'] = i;
    		else{
    			int pos = i - a[s[i]-'a'];
    			an[s[i]-'a'] = min(an[s[i]-'a'], pos);
    			a[s[i]-'a'] = i;
			}
		}
		else{
    		if(A[s[i]-'A'] == -1) A[s[i]-'A'] = i;
    		else{
    			int pos = i - A[s[i]-'A'];
    			An[s[i] - 'A'] = min(An[s[i] - 'A'], pos);
    			A[s[i]-'A'] = i;
			}
		}
	}
	for(int i = 0; i < 26; i++){
		if(a[i] == -1 || an[i] == INF) continue;
		else printf("%c:%d\n", 'a'+i, len-an[i]); 
	}
	for(int i = 0; i < 26; i++){
		if(A[i] == -1) continue;
		else printf("%c:%d\n", 'A'+i, len-An[i]); 
	}
    return 0;
}

F. Mo的极限

这个题出得很李战士。

要注意-0x^k 以及 同类项的合并。

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const int maxn = 1e7 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

char u[maxn], d[maxn];
int upcnt, lowcnt;
struct node{
    int k, n;
}up[maxn], low[maxn];

int gcd(int a, int b){
    return b == 0 ? a : gcd(b, a % b);
}
bool cmp(node a, node b){
    return a.n > b.n;
}

int main(){
    scanf("%s%s", u, d);
    int lu = strlen(u);
    int ld = strlen(d);
    for(int i = 0; i < lu; i++){
        if(u[i] == 'x'){
            int pos = i-1, temp = 0, op = 1;
            while(u[pos] >= '0' && u[pos] <= '9') pos--;
            if(u[pos] == '-') op = -1;
            pos ++;
            for(; pos < i; pos++)
                temp = temp * 10 + (u[pos] - '0');
            if(temp == 0) continue;
            if(op == -1) temp *= op;
            up[upcnt].k = temp;
            pos = i+2; temp = 0; op = 1;
            while(u[pos] >= '0' && u[pos] <= '9')pos++;
            for(int j = i+2; j < pos; j++)
                temp = temp * 10 + (u[j] - '0');
            up[upcnt++].n = temp;
        }
    }
    for(int i = 0; i < ld; i++){
        if(d[i] == 'x'){
            int pos = i-1, temp = 0, op = 1;
            while(d[pos] >= '0' && d[pos] <= '9')pos--;
            if(d[pos] == '-') op = -1;
            pos ++;
            for(; pos < i; pos++)
                temp = temp * 10 + (d[pos] - '0');
            if(temp == 0) continue;
            if(op == -1) temp *= op;
            low[lowcnt].k = temp;
            pos = i+2; temp = 0; op = 1;
            while(d[pos] >= '0' && d[pos] <= '9')pos++;
            for(int j = i+2; j < pos; j++)
                temp = temp * 10 + (d[j] - '0');
            low[lowcnt++].n = temp;
        }
    }
    sort(up, up+upcnt, cmp);
    sort(low, low+lowcnt, cmp);
    for(int i = 1; i < upcnt; i++)
        if(up[i].n == up[0].n) up[0].k += up[i].k;
    for(int i = 1; i < lowcnt; i++)
        if(low[i].n == low[0].n) low[0].k += low[i].k;
    if(lowcnt == 0 || upcnt == 0) {
        printf("0\n"); return 0;
    }
    if(up[0].n == low[0].n){
        int tex = gcd(up[0].k, low[0].k);
        int xx = up[0].k/tex, yy = low[0].k/tex;
        if(yy == 1 || yy == -1) printf("%d\n", xx);
        else{
            if((xx>0 && yy >0) || (xx < 0 && yy < 0))printf("%d/%d\n", xx, yy);
            else printf("%d/%d\n", abs(xx)*-1, abs(yy));
        }
    }
    else if(up[0].n > low[0].n){
        if(up[0].k == 0) printf("0\n");
        else printf("oo\n");
    }
    else printf("0\n");
    return 0;
}

/*
-1000x^20+1000x^2
10000x^20-1000x^20

-1x^10+1x^10+0x^1
1x^0
*/

G. Mo的数学

正解为容斥定理,我用的质因数分解+打标记水过

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const ll maxn = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;

bool vis[maxn];
ll a[maxn];
ll n, m, num;
void get_factor(int x){
	for(int i = 2; i*i <= x; i++){
		if(x % i == 0){
			a[num++] = i;
			while(x % i == 0){
				x /= i;
			}
		}
	}
	if(x != 1) a[num++] = x;
}

int main(){
	while(scanf("%d%d", &n, &m) != EOF){
		clr(a); num = 0;
		memset(vis, 1, sizeof(vis));
		get_factor(m);
		//line;
		ll ans = 1;
		for(int i = 0; i < num; i++){
			ll t = a[i];
			for(int j = 1; t*j <= n; j++){
				vis[t*j] = false;
			}
		}
		for(int i = 2; i <= n; i++){
			if(vis[i]) ans = ((ans % MOD )* (i % MOD )) % MOD;
		}
		printf("%lld\n", ans);
	}
    return 0;
}

 

标程:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int MOD = 1e9 + 7;
const int N = 1e6;

int fac[N + 1] ;
void init(int n){
    fac[0] = 1;
    for (int i = 1; i <= n; i++){
        fac[i] = fac[i - 1] * 1ll *  i % MOD; 
    }
}

int inv (int a, int b, int c){
    int s = 1, base = a % c;
    while(b){
        if(b & 1) s = s * 1ll * base % c;  
        base = base * 1ll * base % c;
        b >>= 1; 
    }
    return s;
}

int prm[30], sz = 0;
void get_prim(int n){
	sz = 0;
    for (ll i = 2; i * i <= n; i++){
        if(n % i == 0){
            prm[sz++] = i;
            while(n % i == 0)  n /= i;
        }
    }
    if(n != 1) prm[sz++] = n;
   // for(int i = 0; i < sz; i++) cout << prm[i] <<"\n";
}
int main(){
    int n, m; 
    init(N);
	while(cin >> n >> m){
	    get_prim(m); 
	    int ans = 1;
	    for (int i = 0; i < (1 << sz); i++){
	        int p = 1, cnt = 0;
	        for (int j = 0; j < sz; j++){
	            if(i >> j & 1){
	                p *= prm[j];
	                cnt ++;
	            }
	        }
	        
	        int s = n / p;
	        int val = fac[s] * 1ll * inv(p, s, MOD) % MOD;
	        ans = ans * 1ll * ((cnt & 1) ? inv(val, MOD - 2, MOD) : val) % MOD; 
	        //cout << ans <<"\n";
	    }
	    cout << ans <<"\n";
	}
    return 0;
}

 

H. Mo的面积

简单计算几何

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;


int main(){
    int x1,x2,y1,y2;
    int q1,q2,w1,w2;
    while(cin>>x1>>y1>>x2>>y2>>q1>>w1>>q2>>w2){
        int xx=max(min(x1,x2),min(q1,q2));
        int yy=max(min(y1,y2),min(w1,w2));
        int xxup=min(max(x1,x2),max(q1,q2));
        int yyup=min(max(y1,y2),max(w1,w2));
        int ans = 0;
		if(xxup>xx)
        	ans = fabs((xx)-(xxup))*fabs((yy)-(yyup));
        int a = fabs(x1-x2) * fabs(y1-y2);
        int b = fabs(q1-q2) * fabs(w1-w2);
        ans = a + b - ans;
        cout << ans << endl;
    }

}

I. 安全距离

高级计算几何,待补

J. 简单递归

签到题

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = (int)1e9 + 7;

int main(){
	int t;
	cin >> t;
	int a[maxn];
	a[0] = a[1] = a[2] = 1;
	for(int i = 3; i <maxn; i++){
		a[i] = ((a[i-1] << 1) % MOD + (a[i-2] >> 1)) % MOD;
	}
	while(t--){
		int n;
		scanf("%d", &n);
		printf("%d\n",a[n]);
	}
	return 0;
}

K. 高度期望

签到题

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;

int n, num = 0, k, a[maxn];

int main(){
	
	ll sum = 0;
	cin >> n >> k;
	for(int i = 0; i < n; i++){
		scanf("%d", &a[i]);
		sum += a[i];
	}
	sort(a, a+n);
	while(sum < k * n){
		sum += (1000-a[num]);
		num++;
	}
	cout << num << endl;
	return 0;
}

L. 最优规划

最小生成树模板,

#include<bits/stdc++.h>
using namespace std;
#define clr(a) memset(a, 0, sizeof(a))
#define line cout<<"--------------"<<endl

typedef long long ll;
const ll maxn = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const ll N = 100010;

ll n, m, s;
ll x, y, d;
ll pre[N];
struct node{
	ll x, y, d;
}p[N];

ll find(ll x){
	if(x == pre[x]) return x;
	else return pre[x] = find(pre[x]);
}
void mix(ll x, ll y){
	ll dx = find(x);
	ll dy = find(y);
	if(dx != dy) pre[dx] = dy;
}
bool cmp(node a, node b){
	return a.d < b.d;
}

int main(){
    scanf("%lld%lld%lld", &n, &m, &s);
    for(ll i = 0; i <= n; i++){
    	pre[i] = i;
	}
	for(ll i = 0; i < m; i++){
		scanf("%lld%lld%lld", &x, &y, &d);
		mix(x, y);
	}
	for(ll i = 0; i < s; i++){
		scanf("%lld%lld%lld", &p[i].x, &p[i].y, &p[i].d);
	}
	sort(p, p+s, cmp);
	ll sum = 0;
	bool flag = false;
	for(ll i = 0; i < s; i++){
		ll dx = find(p[i].x);
		ll dy = find(p[i].y);
		if(dx != dy){
			sum += p[i].d;
			pre[dx] = dy;
		}
	}
	ll cnt = 0;
	for(ll i = 1; i <= n; i++){
		if(i == find(i)) cnt++;
	}
	if(cnt == 1) printf("%lld\n", sum);
	else printf("Concubines can't do it.\n");
    return 0;
}

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值