1. 程式人生 > >Educational Codeforces Round 54 (Rated for Div. 2)A B C D

Educational Codeforces Round 54 (Rated for Div. 2)A B C D

題意:問最多刪去一個字元,如何變為字典序最小的串。 題解:明顯是貪心了,從前往後刪,找到第一個s[i]>s[i+1]s[i] > s[i + 1]的刪去即可。找不到就刪去最後一個字元。

#include<bits/stdc++.h>

using namespace std;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int n;
	string s;
	cin>>n>>s;
	string t =
""; for(int i = 0; i < s.length(); ++i){ if(i == 0 && s[0] > s[1]) { t = s.substr(1,s.length()); break; } if(i == n - 1) { t = s.substr(0,s.length() - 1); break; } if(s[i] > s[i + 1]) { t = s.substr(0,i) + s.substr(i + 1,s.length()); break; } } cout<<
t <<endl; return 0; }

程式碼

題意:nn不斷減去最小當前值的最小質因子,問最後變為00至少需要多少次。 題解:

很容易發現如果是質數,只要減一次即可; 如果是偶數只需要減n2\frac{n}{2}次; 如果是奇數,就強行暴力減成偶數,再直接算出來即可。

程式碼

#include<bits/stdc++.h>

using namespace std;
const int N = 100100;
int prime[N];
bool vis[N];
int init()
{
	int k = 0;
	for(int i = 2; i <
N; ++i) { if(vis[i] == 0) { prime[k++] = i; } for(int j = 2; j * i < N; ++j) { if(vis[i * j] == 0) { vis[i * j] = 1; } } } return k; } bool isPrime(long long n) { for(int i = 2; 1LL * i * i <= n; ++i) { if(n % i == 0) return 0; } return 1; } int main() { #ifndef ONLINE_JUDGE freopen("input.in","r",stdin); #endif long long n; int cnt = init(); long long ans = 0; cin>>n; if(isPrime(n)) { cout<<1<<endl; return 0; } if(n % 2 == 0) { cout<<n / 2<<endl; return 0; } for(int i = 0; i < cnt; ++i) { while(n % prime[i] == 0) { if(n - prime[i] >= 0) n -= prime[i]; ans++; if(n % 2 == 0) { ans += n / 2; n = 0; break; } //cout<<prime[i]<<endl; if(n == 0) break; } if(n == 0) break; } cout<< ans <<endl; return 0; }

題意:問滿足a+b=d,ab=da + b = d,a\cdot b = daabb。 題解:首先容易發現明顯是個二元一次方程,所以解一下就會發現a,ba,b的範圍在[d2,d][d-2,d],然後二分即可。

程式碼

#include<bits/stdc++.h>

using namespace std;
int d;
long double ans = 0;
bool love(long double x)
{
	if(x * ((long double)d - x) > d) {
		return 1;
	}
	return 0;
	
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int t;
	cin>>t;
	while(t--) {
		cin>>d;
		int f = 0;
		long double l = d - 2, r = d;
		if(d < 4) {
			if(d == 0) {
				printf("Y %.9f %.9f\n",0.0,0.0);
				continue;
			}else{
				printf("N\n");
				continue;
			}
		}
		if(d >= 4)
		while(l < r) {
			long double mid = (l + r) / 2, a = mid, b = d - mid;
			if(fabs(a * b - d) <= 1e-7) {
				ans = mid;
				break;
			}
			if(love(mid))
				l = mid;
			else
				r = mid;
		}
		if(ans){
			printf("Y %.9f %.9f\n",(double)ans,(double)(d-ans));
		}else{
			printf("N\n");
		}
	}
	
    return 0;
}

題意:nn個點mm條邊,最多保留kk條邊,問最後在保證最短路徑不變並且點儘可能多的情況下的圖中剩餘的路徑編號。 題解:首先通過dijkstradijkstra跑一遍,得出來的最短路徑一定是一棵樹,所以為了點儘可能多隻要保留最先找到的kk條邊即可。

程式碼

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
#define Pii pair<LL,int>
#define P pair<LL,Pii>
const int N = 300100;
int n,m,k,from[N];

LL dis[N];
vector<int> ans;
vector<P> E[N];
void dijkstra(int s)
{
	memset(dis,0x3f3f,sizeof dis);
	dis[s] = 0;
	priority_queue<Pii, vector< Pii >, greater< Pii > > pq;
	pq.push({dis[s],s});
	int cnt = 0;
	while(cnt < k && !pq.empty()) {
		Pii cur = pq.top();
		pq.pop();
		LL d = cur.first;
		int u = cur.second;
		if(dis[u] < d) continue;
		if(u != 1) {
			cnt++;
			ans.push_back(from[u]);
		}
		for(P t : E[u]) {
			LL w = t.first;
			int f = t.second.second, v = t.second.first;
			if(dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				from[v] = f;
				pq.push({dis[v],v});
			}
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
	int x,y,w;
	cin>>n>>m>>k;
	for(int i = 1; i <= m; ++i) {
		cin>>x>>y>>w;
		E[x].push_back({w,{y,i}});
		E[y].push_back({w,{x,i}});
	}
	dijkstra(1);
	cout << ans.size() << endl;
	for(int iter : ans) {
		cout<< iter << ' ';
	}
	cout<<endl;
    return 0;
}