codeforces Edu 104 DE

ABC挺顺的,D卡飞我是没想到的…(btw还好wa1不算罚时不然我直接炸开(这里因为算错了一个复杂度,等会补上来,白痴问题我这就公开处刑我自己

D

2s时限 ,我寻思cf的评测姬不会爆吧,那这不是直接搞就完事(

就搁那硬扫1e9,没注意中间sqrt函数也有个复杂度没算进去

后来是打表看了眼上限然后预处理做的

也整挺短一code

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

typedef long long ll;
vector<int> vec;

int main() {
    
    
 	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

	for(ll i = 3; i <= 44721; i += 2) {
    
    
		ll x = (i * i + 1) / 2; 
		if(x * x - (x - 1) * (x - 1) == i * i) vec.push_back(x);
	}
    
//	cout << vec.size();
	int T;
	cin >> T;
	while(T--) {
    
    
		int n;
		cin >> n;
		cout << upper_bound(vec.begin(), vec.end(), n) - vec.begin() << endl;
	}
	
}

1487 E. Cheap Dinner

题意: 有4种食物,设为ABCD,各有 n 1 , n 2 , n 3 , n 4 n1,n2,n3,n4 n1,n2,n3,n4个,每个都有一个 c o s t cost cost,同时 A B AB AB之间有 m 1 m1 m1种冲突的搭配, B C BC BC之间有 m 2 m2 m2种冲突的搭配, C D CD CD之间有 m 3 m3 m3种冲突的搭配,现在要四种食物各取一个问最少花费

思路: 因为AD之间不冲突,可以先把整个问题分成两部分考虑(A-B,C-D),

在考虑A-B的时候,对于每个B(因为B在中间,由B选择A没有后效性)贪心选择cost最小的A,判断A是否在m1个冲突里可以用set的find,对于每个B存一个set,总体复杂度在 O ( n l o g m ) O(nlogm) O(nlogm)级别,(可以证明枚举每个A的时候,如果最开始的每次都恰巧冲突,最多的冲突次数大概是 m+n2 次,) 直接把答案加在B里就行

C-D同理,对每个C存set,把答案加在C里

最后也是同理把两部分和在一起,这里对B或C存set都行
参考YT

codeforces_SAMPLE I
在这里插入图片描述

code:

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

const int N = 150010, M = 200010;
const int inf = 5e8;

struct node {
    
    
	int cost, idx;
	bool operator < (const node & obj) const{
    
    
		return cost < obj.cost;
	} 
}mpa[N], mpb[N], mpc[N], mpd[N];

set<int> stb[N], stc[N], ss[N];

int main() {
    
    
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	
	int numa, numb, numc, numd;
	cin >> numa >> numb >> numc >> numd;
	
	for(int i = 1; i <= numa; ++ i) {
    
     // a
		mpa[i].idx = i;
		cin >> mpa[i].cost;
	}
	for(int i = 1; i <= numb; ++ i) {
    
     // b 
		mpb[i].idx = i;
		cin >> mpb[i].cost;
	}
	for(int i = 1; i <= numc; ++ i) {
    
     // c
		mpc[i].idx = i;
		cin >> mpc[i].cost;
	}
	for(int i = 1; i <= numd; ++ i) {
    
     // d 
		mpd[i].idx = i;
		cin >> mpd[i].cost;
	}
	
	int m1, m2, m3;
	cin >> m1;
	for(int i = 1, u, v; i <= m1; ++ i) {
    
     // a and b (in b 
		cin >> u >> v;
		stb[v].insert(u);
	}
	cin >> m2;
	for(int i = 1, u, v; i <= m2; ++ i) {
    
     // b and c (in c 
		cin >> u >> v;
		ss[v].insert(u);
	}
	cin >> m3;
	for(int i = 1, u, v; i <= m3; ++ i) {
    
     // c and d (in c 
		cin >> u >> v;
		stc[u].insert(v);
	}
	
	sort(mpa + 1, mpa + numa + 1); // a and b 
	for(int i = 1; i <= numb; ++ i) {
    
    
		bool flag = 0; 
		for(int j = 1; j <= numa; ++ j) {
    
    
			if(stb[mpb[i].idx].find(mpa[j].idx) == stb[mpb[i].idx].end()) {
    
    
				mpb[i].cost += mpa[j].cost;
				flag = 1;
				break; 
			}
		}
		if(!flag) {
    
    
			mpb[i].cost = inf;
		}
	} 
	
	sort(mpd + 1, mpd + numd + 1); // c and d 
	for(int i = 1; i <= numc; ++ i) {
    
    
		bool flag = 0; 
		for(int j = 1; j <= numd; ++ j) {
    
    
			if(stc[mpc[i].idx].find(mpd[j].idx) == stc[mpc[i].idx].end()) {
    
    
				mpc[i].cost += mpd[j].cost;
				flag = 1;
				break; 
			}
		}
		if(!flag) {
    
    
			mpc[i].cost = inf;
		}
	} 

	sort(mpb + 1, mpb + numb + 1); // (a and b (in b)) and (c and d (in c)) 
	for(int i = 1; i <= numc; ++ i) {
    
    
		bool flag = 0; 
		for(int j = 1; j <= numb; ++ j) {
    
    
			if(ss[mpc[i].idx].find(mpb[j].idx) == ss[mpc[i].idx].end()) {
    
    
				mpc[i].cost += mpb[j].cost;
				flag = 1;
				break; 
			}
		}
		if(!flag) {
    
    
			mpc[i].cost = inf;
		}
	} 

	sort(mpc + 1, mpc + numc + 1);
	
	if(mpc[1].cost >= inf) {
    
    
		cout << -1;
		return 0;
	} 
	else {
    
    
		cout << mpc[1].cost;
	}
} 

代码很多部分都是cv了改下,没有想得那么烦

btw,cf数据有点水啊,刚有个地方打错数组都能给我过23个点,还以为是边界啥的出问题了(= =

F

数位dp
挖坑

参考blog

  1. eg 111111 × 6 = 1111111 − 111111 × 4 − 1 111111\times 6=1111111-111111 \times 4-1 111111×6=1111111111111×41, 1 × 6 = 11 − 1 × 5 1\times 6=11-1\times 5 1×6=111×5,所以表明每一个长度的串1都最多用不会超过6次
  2. 低位的1不会产生进位,即不会对高位产生影响,

猜你喜欢

转载自blog.csdn.net/qq_39602052/article/details/113852759
DE