zoukankan      html  css  js  c++  java
  • NOI2010Day1

    T1 能量采集

    显然对于每个点采集时(k = gcd(i, j) - 1), 则

    [ans = sum_{i = 1}^{n}sum_{j = 1}^{m}(2 * gcd(i, j) - 1) \ ans = 2 * (sum_{i = 1}^{n}sum_{j = 1}^{m}gcd(i, j)) - n * m \ 欧拉反演得 \ ans = 2 * (sum_{d = 1}^{n}phi(d)lfloorfrac{n}{d} floorlfloorfrac{m}{d} floor) - n * m ]

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    #define N 100005
    
    int n, m, prime[N], cnt = 0;
    
    ll phi[N];
    
    bool isprime[N];
    
    void Init(int n)
    {
    	isprime[1] = 1;
    	phi[1] = 1;
    	for(int i = 2; i <= n; i++)
    	{
    		if(!isprime[i]) prime[++cnt] = i, phi[i] = i - 1;
    		for(int j = 1; j <= cnt && i * prime[j] <= n; j++)
    		{
    			isprime[i * prime[j]] = 1;
    			if(i % prime[j] == 0)
    			{
    				phi[i * prime[j]] = phi[i] * prime[j];
    				break;
    			}
    			phi[i * prime[j]] = phi[i] * phi[prime[j]];
    		}
    	}
    	for(int i = 2; i <= n; i++) phi[i] += phi[i - 1];
    }
    
    int main()
    {
    	cin >> n >> m;
    	if(n > m) swap(n, m);
    	Init(n);
    	ll ans = 0;
    	for(int l = 1, r; l <= n; l = r + 1)
    	{
    		r = min(n / (n / l), m / (m / l));
    		ans += (phi[r] - phi[l - 1]) * (n / l) * (m / l);
    	}
    	printf("%lld
    ", ans * 2 - 1ll * n * m);
    	return 0;
    }
    

    T2 超级钢琴

    对每个点找出范围里的最大值,然后每次取完之后把两边两段加入,在堆中按区间最大值排序取k个即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 500005
    typedef long long ll;
    
    int n, k, L, R;
    
    ll a[N];
    
    int st[20][N];
    
    int Log2(int x) {return log(x) / log(2);}
    
    int query(int l, int r)
    {
    	int len = log2(r - l + 1);
    	return (a[st[len][l]] >= a[st[len][r - (1 << len) + 1]]) ? st[len][l] : st[len][r - (1 << len) + 1];
    }
    
    struct point
    {
    	int o, l, r, val;
    
    	bool operator < (const point &s) const
    	{
    		return a[val] -  a[o - 1] < a[s.val] - a[s.o - 1];
    	}
    };
    
    priority_queue <point> pq;
    
    int main()
    {
    	scanf("%d%d%d%d", &n, &k, &L, &R);
    	for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    	for(int i = 2; i <= n; i++) a[i] += a[i - 1];
    	for(int i = 1; i <= n; i++) st[0][i] = i;
    	for(int i = 1; i <= 19; i++)
    		for(int j = 1; j <= n - (i << 1) + 1; j++)
    		{
    			if(a[st[i - 1][j]] >= a[st[i - 1][j + (1 << i - 1)]]) st[i][j] = st[i - 1][j];
    			else st[i][j] = st[i - 1][j + (1 << i - 1)];
    			// cout << i << ' ' << j << ' ' << a[st[i][j]] << endl;
    		}
    	for(int i = 1; i <= n; i++)
    	{
    		int l = i + L - 1, r = min(i + R - 1, n);
    		if(l > n) break;
    		pq.push((point){i, l, r, query(l, r)});		
    	}	
    	ll ans = 0;
    	while(k--)
    	{
    		point u = pq.top();
    		pq.pop();
    		// cout << u.o << ' ' << u.val << endl;
    		ans += a[u.val] - a[u.o - 1];
    		int x = u.val;
    		if(u.l <= x - 1) pq.push((point){u.o, u.l, x - 1, query(u.l, x - 1)});
    		if(x + 1 <= u.r) pq.push((point){u.o, x + 1, u.r, query(x + 1, u.r)});
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    

    T3 海拔

    首先发现取值只会是0或1, 然后可知两者都会只有一个联通块,体力消耗就是两个联通块中间连着的那些边。所以起点和终点的最小割就是答案。平面图转对偶图求一求就好了

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    #define N 350005
    
    int n, head[N], nxt[N << 2], to[N << 2], cnt = 0;
    
    ll val[N << 2];
    
    void add(int x, int y, ll z)
    {
    	cnt++;
    	to[cnt] = y, val[cnt] = z, nxt[cnt] = head[x], head[x] = cnt;
    }
    
    ll dis[N];
    
    bool vis[N];
    
    struct point
    {
    	int x; ll dis;
    
    	bool operator < (const point &o) const 
    	{
    		return dis > o.dis;
    	}
    };
    
    priority_queue <point> q;
    
    int s = 0, t;
    
    ll ans = 0;
    
    void dij()
    {
    	memset(dis, 0x3f, sizeof(dis));
    	dis[s] = 0;
    	q.push((point){s, 0});
    	while(!q.empty())
    	{
    		point u = q.top(); q.pop();
    		int x = u.x;
    		if(vis[x]) continue;
    		vis[x] = 1;
    		for(int p = head[x]; p; p = nxt[p])
    		{
    			int v = to[p];
    			// cout << ' ' << x << ' ' << v << endl;
    			if(dis[v] > dis[x] + val[p])
    			{
    				dis[v] = dis[x] + val[p];
    				q.push((point){v, dis[v]});
    			}
    		}
    	}
    	printf("%lld
    ", dis[t]);
    }
    
    int main()
    {
    	scanf("%d", &n);
    	t = n * n + 1;
    	for(int i = 1; i <= n + 1; i++)	
    		for(int j = 1; j <= n; j++)
    		{
    			int x;
    			scanf("%d", &x);
    			int k = (i - 1) * n + j;
    			// cout << s << ' ' << k << ' ' << t << endl;
    			if(i == 1) add(k, t, x);
    			else if(i == n + 1) k -= n, add(s, k, x);
    			else add(k, k - n, x);
    		}
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= n + 1; j++)
    		{
    			int x;
    			scanf("%d", &x);
    			int k = (i - 1) * n + j;
    			if(j == 1) add(s, k, x);
    			else if(j == n + 1) k--, add(k, t, x);
    			else add(k - 1, k, x);
    		}
    	for(int i = 1; i <= n + 1; i++)	
    		for(int j = 1; j <= n; j++)
    		{
    			int x;
    			scanf("%d", &x);
    			int k = (i - 1) * n + j;
    			if(i == 1) add(t, k, x);
    			else if(i == n + 1) k -= n, add(k, s, x);
    			else add(k - n, k, x);
    		}
    	for(int i = 1; i <= n; i++)
    		for(int j = 1; j <= n + 1; j++)
    		{
    			int x;
    			scanf("%d", &x);
    			int k = (i - 1) * n + j;
    			if(j == 1) add(k, s, x);
    			else if(j == n + 1) k--, add(t, k, x);
    			else add(k, k - 1, x);
    		}
    	// for(int i = s; i <= t; i++)
    	// {
    	// 	cout << i << ' ';
    	// 	for(int p = head[i]; p; p = nxt[p])
    	// 		cout << to[p] << ' ' << val[p] << ' ';
    	// 	cout << endl;
    	// }
    	dij();
    	return 0;
    }
    
  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/LJB00131/p/13229368.html
Copyright © 2011-2022 走看看