1. 程式人生 > 其它 >20.11.13模擬 挑戰nbc(nbc)

20.11.13模擬 挑戰nbc(nbc)

給定1~n,每次可以合併兩個數字,得到平均值,求怎麼合併能使得最後剩下的數字最大

顯然每次選擇最小的兩個數字合併是最優策略。我們可以對每個數字用一個加權值 ,顯然越大的數字這個權值要用越大的加權值,最大的合併一次,用0.5,次大的合併兩次用0.25.
這樣我們就可以O(n)解決了。其實1~n這些固定數字顯然可以化簡式子

\[ \begin{array}{l} S_{n}&=\frac{1}{2^{n}}+\frac{2}{2^{n-1}}+\cdots+\frac{n}{2}(1) \\ 由等比數列求和公式 S_{n}&=\frac{a_1 (1-q^n)}{1-q} =1 \\ 2 S_{n}&=\frac{1}{2^{n-1}}+\frac{2}{2^{n-2}}+\cdots+n(2) \\ \text { (2) }-(1) S_{n}&=n-\frac{1}{2^{n}}-\frac{1}{2^{n-1}}-\cdots-\frac{1}{2}=n-1+\frac{1}{2^{n}} \\ a n s=S_{n}+\frac{1}{2^{n}}&=n-1+\frac{1}{2^{n-1}} \end{array} 去年我寫了個矩陣不知道幹什麼的。。如果看得懂可否告訴我。 \]
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i(j);i<=k;++i)
#define drp(i,j,k) for(register int i(j);i>=k;--i)
using namespace std;
typedef long long lxl;
inline char gt()
{
//	return getchar();
	static char buf[1<<21],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;
}
template <typename T>
inline void  read(T &x)
{
	register char ch = gt();
	x = 0;
	int w(0);
	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
	w ? x = ~(x - 1) : x;
}
template <typename T>
inline void out(T x)
{
	if(x < 0) x = -x, putchar('-');
	char ch[20];
	int num(0);
	while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
	while(num) putchar(ch[num--]);
	putchar('\n');
}
const int N = 1e9;
vector<double>v;
int n;

const int mod = 1e9 + 7;
inline lxl qpow(lxl a, int b)
{
	lxl r(1);
	for(; b; a = a * a % mod, b >>= 1) if(b & 1) r = r * a % mod;
	return r;
}

struct matrix
{
	lxl a[5][5];
	int n, m;
	matrix()
	{
		memset(a, 0, sizeof a);
	}
} I, A;
matrix operator *(const matrix &x, const matrix & y )
{
	matrix a;
	a.n = x.n;
	a.m = y.m;
	rep(i, 1, x.n)
	rep(j, 1, y.m)
	rep(k, 1, x.m)
	a.a[i][j] = (a.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod;
	return a;
}

namespace one{
	int main(){
		cout<<(n-1+qpow(qpow(2,n-1),mod-2) ) %mod;
		return 0;
	}
}

int main()
{
	freopen("nbc.in", "r", stdin);
	freopen("nbc.out", "w", stdout);
	read(n);
	
	one::main();
	return 0;
	
	lxl k = n - 1;
	A.n = 1;
	A.m = 3;
	A.a[1][1] = 1;
	A.a[1][2] = 2;
	A.a[1][3] = 1;

	I.n = I.m = 3;
	I.a[1][1] = I.a[2][1] = qpow(2, mod - 2);
	I.a[2][2] = I.a[3][2] = I.a[3][3] = 1;
	while(k)
		{
			if(k & 1) A = A * I;
			I = I * I;
			k >>= 1;
		}
	out(A.a[1][1] % mod);
	return 0;
}

本文來自部落格園,作者:{2519},轉載請註明原文連結:https://www.cnblogs.com/QQ2519/p/15376641.html