CF338(div2)

A. Bulbs

题目描述:

就是有m盏灯,有n个开关,一开始灯都是关的,然后按下一个开关后就会使某些灯打开,然后打开的灯不会再次熄灭。问能否是所有的灯打开。

解答:

简单的遍历一下,然后看是否存在有灯不受开关控制。

#include <iostream>
using namespace std;

int num[105], n, m;

void solve()
{
	int cnt = 0;
	for(int i = 0; i < m; i ++) num[i] = 0;
	
	int geshu, val;
	for(int i = 0; i < n; i ++){
		cin>>geshu;
		for(int j = 0; j < geshu; j ++){
			cin>>val;
			if(num[val -= 1] == 0)
				cnt ++;
			num[val] = 1;
		}
	}
	cout<< ((cnt == m) ? "YES" :  "NO") <<endl;
}

int main()
{
	while(cin>>n>>m){
		solve();
	}
}

B. Longtail Hedgehog

题目描述:

就是可以用别画个dog,然后每个点有一个数字,然后告诉你m对连接的数字,dog由脊柱和尾巴构成,脊柱为数字,只能从小到大构成脊柱,尾巴可以为多条,长度为1。现在定义一个值,该值是由尾巴的条数乘以脊柱的长度的积得到,现在要求这个值的最大值。

解答:

因为脊柱数字时从小到大的,那么在求解脊柱长度时,可以得到五环有向图,然后针对有向图求度数,运用DAG+dp可以得到每个点的深度的最大值,即脊柱的最大值,然后根据无向图的该点边的个数,可以得到尾巴长度。然后遍历一下求最大值即可。

#include <iostream>
#include <queue>
#include <cmath>
#include <cstdio>
using namespace std;

int n, m, dree[100005], dushu[100005];
vector<int> G[100005];
bool isVisit[100005];


void solve()
{
	fill(dree, dree + n, 0);
	fill(dushu, dushu + n, 0);
	for(int i = 0; i < n; i ++) G[i].clear();

	int u, v;
	for(int i = 0; i < m; i ++){
		cin>>u>>v;
		u -= 1, v -= 1;
		if(u > v) swap(u, v);
		G[u].push_back(v);
		G[v].push_back(u);
		dushu[v] ++;
	}

	queue<int> q;
	for(int i = 0; i < n; i ++){
		if(dushu[i] == 0){
			dree[i] = 1;
			q.push(i);
		}
	}

	while(!q.empty()){
		int t = q.front();
		q.pop();
		int len = G[t].size();
		for(int i = 0; i < len; i ++){
			if(G[t][i] < t) continue;
			dree[G[t][i]] = max(dree[G[t][i]], dree[t] + 1);
			dushu[G[t][i]] --;
			if(dushu[G[t][i]] == 0) q.push(G[t][i]);
		}
	}

	fill(isVisit, isVisit + n, false);
	__int64 ans = 0;
	for(int i = 0; i < n; i ++){
		ans = max(ans, 1LL * G[i].size() * dree[i]);
	}
	cout<<ans<<endl;
}

int main()
{
	while(cin>>n>>m){
		solve();
	}
}
C. Running Track

题目描述:

就是有两个字符串s,t。然后t可以分成很多子串,这些子串必须出现在s中,或者s的翻转串中,问分成子串个数最少的方案。
解答:

题目数据量不大字符串的长度为2100,所以运用最大匹配的方法,例如t的前i个字符能在s或者f反s中找到,且前i+1个不能在二者中找到,那么这前i个字符就是子串之一,一直这样进行下去。查找时,使用KMP,时间复杂度为O(n^2)

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

int Next[2105];

void getNext(char *s)
{
	int len = strlen(s);
	fill(Next, Next + len, -1);
	int i = 0, j = -1;
	while(i < len){
		if(j == -1 || s[i] == s[j]){
			i ++, j ++;
			if(i >= len) break;
			if(s[i] != s[j]) Next[i] = j;
			else Next[i] = Next[j];
		}
		else j = Next[j];
	}
}

int Kmp(char *s1, char *s2)
{
	int len1 = strlen(s1), len2 = strlen(s2), i = 0, j = 0, st = 0;
	while(i < len1){
		if(j != -1 && s1[i] == s2[j]){
			i ++, j ++;
			if(j >= len2) return i - strlen(s2);
		}
		else j = Next[j];
		if(j == -1){
			i ++;
			st = i;
			j = 0;
		}
	}
	return  -1;
}

char s1[2103], s2[2103], s3[2103], s4[2103];
int cnt, st[2103], et[2103];

void solve()
{
	int len1 = strlen(s1), len2 = strlen(s2);
	for(int i = 0; i <= len2 / 2; i ++)
		 s3[i] = s2[len2 - i - 1], s3[len2 - i - 1] = s2[i];
	s3[len2] = 0;
	
	cnt = 0;
	int curSt = 0;
	int ans1, ans2;
	s4[0] = 0;
	for(int i = 0; i < len1; i ++){
		if(curSt == i){
			s4[0] = s1[i];
			s4[1] = 0;
		}
		else{
			int len = strlen(s4);
			s4[len] = s1[i];
			s4[len + 1] = 0;
		}
		getNext(s4);		
		int t = Kmp(s2, s4);
		if(t == -1){
			t = Kmp(s3, s4);
			if(t == -1){
				if(curSt == i){
					cout<<"-1"<<endl;
					return;
				}
				else{
					st[cnt] = ans1;
					et[cnt] = ans2;
					cnt ++, curSt = i;
					i --;
				}
			}
			else{
				ans1 = len2 - 1 - t;
				ans2 = len2 - 1 - (t + i - curSt);
			}
		}
		else{
			ans1 = t;
			ans2 = t + i - curSt;
		}
	}
	st[cnt] = ans1;
	et[cnt] = ans2;

	cout<<cnt + 1<<endl;
	for(int i = 0; i <= cnt; i ++)
		cout<<st[i] + 1<<" "<<et[i] + 1<<endl;
}

int main()
{
	while(cin>>s2>>s1){
		solve();
	}
}
D. Multipliers

题目描述:

就是告诉你一个数可以有p1p2....pm个数相乘得到,且每个pi都是素数。现在要求该数所有因子的乘积,最后结果Mod(10^9 + 7)。

解答:

题目的意思很好理解,假设对p进行排序合并之后,可以得到该数如下表示

          

对于p的贡献进行分析,所有因子中含有p,且除以p之后不能被p整除的个数为(b + 1)(c + 1)个,对于含有p^2的因子个数也是这么多个,所以对于p的贡献积为


对于q,r同理可得,最后的表达式为:

根据上面的式子进行求解即可,注意一些小细节的处理

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

__int64 num[200005], ans;
int cnt[200005];
int m;

const int Mod = 1000000007;

void powV(__int64 temp, int n)
{
	while(n){
		if(n & 1)
			ans = (ans * temp) % Mod;
		temp = temp * temp % Mod;
		n >>= 1;
	}
}

__int64 powVV(__int64 temp, int n)
{
	__int64 aannss = 1;
	while(n){
		if(n & 1)
			aannss = (aannss * temp) % Mod;
		temp = temp * temp % Mod;
		n >>= 1;
	}
	return aannss;
}

void solve()
{
	for(int i = 0; i < m; i ++) cin>>num[i];
	sort(num, num + m);
	int len = m;
	bool isAllEven = true;
	cnt[0] = 1;
	for(int i = 1, j = 0; i < m; i ++){
		if(num[i] != num[j]){
			if(cnt[j] % 2) isAllEven = false; 
			j ++;
			num[j] = num[i];
			cnt[j] = 1;
		}
		else{
			cnt[j] ++;
			len --;
		}
	}
	if(cnt[len - 1] % 2) isAllEven = false;
	
	ans = 1;
	for(int i = 0; i < len; i ++)
		powV(num[i], isAllEven ? cnt[i] / 2 : cnt[i]);

	for(int i = 0; i < len; i ++){
		if(!isAllEven && cnt[i] % 2){
			ans = powVV(ans, (cnt[i] + 1) / 2);
			isAllEven = true;
		}
		else
			ans = powVV(ans, (cnt[i] + 1));
	}
	cout<<ans<<endl;
}

int main()
{
	while(cin>>m){
		solve();
	}
}

E. Hexagons

找规律题,以后再补吧,也有可能 不补。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值