codeforces#837--div2

目录

A. Hossam and Combinatorics

B. Hossam and Friends

C. Hossam and Trainees


A. Hossam and Combinatorics

题目大意:

给定一个长度为n的数组,求数组中两个元素相减绝对值最大的个数。一对下标pair(i, j) 和pair(j, i)都是有贡献的。

思路:

统计最大值和最小值的个数,贡献值就是最大值的数量 * 最小值的数量 * 2, 但是要注意最大值和最小值可能是同一个值,所以我们需要特判一下,具体细节看代码。

#define rep(i,a,n) for (int i=a;i<=n;i++)
#define all(x) (x).begin(),(x).end()
void solve()
{
	int n;
	cin >> n;
	vector<int> a(n), cnt(100010);

	rep(i, 0, n - 1)	cin >> a[i], cnt[a[i]]++;
	sort(all(a));
	if (a[0] == a[n - 1]) {
		cout << 1ll * n * (n - 1) << '\n';
		return;
	}
	cout << 1ll * 2 * cnt[a[n - 1]] * cnt[a[0]] << '\n'; 
}

B. Hossam and Friends

题目大意:

有n个小朋友,编号1~n,给m组关系,每组关系给定两个小朋友的编号x, y, 表示x与y不认识。定义一个子段是好的:在区间[a, b], a,a+1,a+2,...b都互相认识。求有多少个好的子段。

思路:

发现前面的小朋友想跟后面的小朋友构成好的子段,必须后面的小朋友都要相互认识,所以我们考虑从大到小枚举小朋友的编号,动态维护每个小朋友能够向右扩展子段长度的最大编号。但是比赛的时候我是把所有的关系全部用vector存起来了,其实只要维护每个小朋友不认识的朋友的编号最小值。

#define rep(i,a,n) for (int i=a;i<=n;i++)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
void solve()
{
	int n, m;
	cin >> n >> m;
	vector<int> a[n + 1];
	rep(i, 1, m) {
		int l, r;
		cin >> l >> r;
		if (l > r)	swap(l, r);
		a[l].pb(r);
	}
	ll ans = 0;
	int last = n + 1;//表示初始都可以构成好的子段
	for (int i = n; i >= 1; i--) if (SZ(a[i])) {
		sort(all(a[i]));//这里其实可以只维护一个最小值
		last = min(last, a[i][0] - 1);
		ans += last - i + 1;
	}
	else {
			if (last == n + 1) ans += (n - i + 1);
			else ans += (last - i + 1);
		}
	cout << ans << '\n';
}

C. Hossam and Trainees

题目大意:给定一个长度为n的a数组,询问是否存在两个数的最大公约数不为1.如果存在输出YES,否则输出NO。1 <= ai <= 1e9

思路:赛时忘记写一个预判,一直wa... 可以考虑筛出40000内的所有质数,然后枚举这些质数x,看是否存在有两个数都可以整除x,并且用一个vector存储x,表示该下标的值有x的质因子,如果存在的话就可以输出YES,否则如果还存在YES的情况,那就是存在两个数有大于40000的质因子。先把所有的a[i]值用map容器标记,我们枚举每个数,然后整除用之前vector容器存储的质因子,看最后被整除的数是否出现过,如果出现过,我们就输出YES,否则输出NO。

#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define x first
#define y second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db; 
const ll mod=1000000007;
const int N = 100010;
int primes[N];
int cnt;
bool st[N];
//筛质数
void is_prime(int n)
{
    for(int i = 2;i <= n; i++)
    {
        if(!st[i])
        {
            primes[cnt++] = i;
            
        }
        for(int j = 0; j < cnt && primes[j] <= n / i; j++)
            {
                st[primes[j] * i] = true;
                if(i % primes[j] == 0) break;
            }
    }
}
void solve()
{
	int n;
	cin >> n;
	vector<int> a(n);
	rep(i, 0, n - 1) cin >> a[i];
	sort(all(a));
	vector<int> c[n + 1];
    //存储每个a[i]有的质因子(<=10000)。
	for (int i = 0; i < cnt; i++) {
		int num = 0;
		for (int j = n - 1; j >= 0; j--) 
			if ((a[j] % primes[i]) == 0) {
				c[j].push_back(primes[i]);
				num ++;
				if (num >= 2) {
					cout << "YES" << '\n';
					return;
				}
			}
	}
	map<int, int> mp;
	for (int i = 0; i < n; i++)	mp[a[i]] = 1;
	for (int i = n - 1; i >= 0; i--) {
		bool ok = false;
		int len = (int)c[i].size();
		for (int j = 0; j < len; j++) {
			while (a[i] % c[i][j] == 0)	{
				a[i] /= c[i][j];
				ok = true;
			}
		}
        //注意我们这里需要用一个ok标记一下是因为a[i]之前已经被标记过了
        //如果我们不存在小于40000的质因子,那么a[i]这个值就是本身 如果不加
        //ok那么就一个数算了两次
		if (ok && a[i] > 1 && mp[a[i]]) {
			cout << "YES" << '\n';
			return;
		}
		else mp[a[i]] = 1;
	}
	cout << "NO" << '\n';
}
int main() 
{	
	
    ios::sync_with_stdio(false);
	cin.tie(0);
	is_prime(40000);
	int t;
	cin >> t;
	while(t--)
		solve();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值