https://lutece.xyz/contest/detail/9/
题目要找到创世神最少需要抽取的经验等级数,很明显对于两种更改等级方式来说,第一种方式是优先选择的方式。
所以利用贪心思想,我们只需要找到低于k的玩家的等级与k之间的差总和x和高于k的玩家的等级与k之间的差总和y,如果x-y大于零,则输出x-y,表明仍需创世神抽出x-y等级的经验值,否则输出0即可,表明不需要创世神再抽出经验值。
当然,在代码实现时可以在读入n个整数时计算k-a,所有的k-a相加后如果为负数则输出0,否则输出求和后的值便可。
#include
using namespace std;
int main()
{
int n,k,ans=0,num;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&num);
ans+=k-num;
}
if(ans<0) printf("0\n");
else printf("%d\n",ans);
return 0;
}
由于气球碰撞之后交换速度,我们可以看做它们交换了位置,所以只需要分别算出每个气球到达烟囱顶部的时间,取max和min就可以了
#include
#include
#include
#include
using namespace std;
const int maxn=100000+10;
double h[maxn],a[maxn];
int main()
{
int n,L,v;cin>>n>>L>>v;
double N=1e18,M=0;
for (int i = 1; i <= n; i++) {
scanf("%lf%lf",h+i,a+i);
N=min(N,(1.0*L-h[i])/(v+a[i]));
M=max(M,(1.0*L-h[i])/(v+a[i]));
}
printf("%.2f %.2f\n",N,M);
return 0;
}
多写几行
t=0 1
t=1 1/2 0 1/2
t=2 1/4 0 2/4 0 1/4
t=3 1/8 0 3/8 0 3/8 0 1/8
…
我们就能发现,把每一项乘以 2^t ,就成了一个杨辉三角形,即对于 t=x 时,蚂蚁出现在位置 y 的概率P(X,Y)=P(X-1,Y-1)+P(X-1,Y+1),而除了杨辉三角外的项,其余项概率皆为 0。那么我们需要计算的就是一个杨辉三角和 2^t 的值,因为 t<=30 ,刚好用 int 就能装下.知道了这些,接下来就是一个简单的递推,不过最后输出前记得化简。还有需要注意的是 t=0,m=0 时,概率为 1 ,因为 1 是整数,所以直接输出 1 ,而不是 1/1 (题目描述为:若结果不是整数,则以x/y的形式输出)。
#include
int x[22][200];
int y[22];
int main()
{
int t,m,T,p,q;
y[0] = 1;
x[0][1] = 1;
for (int i=1;i<=20;i++)
{
y[i]=y[i-1] * 2;
for (int j=1;j<=i+1;j++)
x[i][j]=x[i-1][j-1] + x[i-1][j+1];
x[i][0]=x[i][2];
}
scanf("%d\n",&T);
while (T--)
{
scanf("%d%d\n",&t,&m);
if (m < 0) m= -m;
if (m > t|| x[t][m + 1]==0){ printf("0\n"); continue; }
if (t==0){ printf("%d\n",x[t][m+1]); continue; }
p=x[t][m + 1];
q=y[t];
while (p % 2==0)
{
p= p/2;
q= q/2;
}
printf("%d/%d\n",p,q);
}
return 0;
}
另外,题目要求给出既约分数,但分母是二的次幂,所以不需要特意用求GCD的算法,直接除2即可。
以上是本题的递推式写法。注意到答案和杨辉三角有关系后,应该想到可以用高中学的组合数解题。
20!在long long int能够表示的范围内,所以可以直接计算。
#include
using namespace std;
long long fac (long long x) {
long long ret = 1;
for (int i = 1; i <= x; i++) ret *= i;
return ret;
}
long long Pow (long long x) {
long long ret = 1;
for (int i = 1; i <= x; i++) ret <<= 1;
return ret;
}
int main (void) {
int kase, t, m;
scanf("%d", &kase);
while (kase--) {
scanf("%d%d", &t, &m);
if (((t + m) % 2 == 0) && abs(m) <= t) {
long long p = fac(t) / fac((m + t) / 2) / fac((t - m) / 2);
long long q = Pow(t);
while (p % 2 == 0) {
p >>= 1;
q >>= 1;
}
if (q != 1) printf("%lld/%lld\n", p, q);
else printf("%lld\n", p);
} else {
printf("0\n");
}
}
}
https://www.cnblogs.com/siuginhung/
一条 Hamilton 路径从 v 0 v_0 v0 依次通过点 v 0 , v 1 , v 2 , ⋯   , v k v_0,v_1,v_2,\cdots,v_k v0,v1,v2,⋯,vk ,最终到达点 v k v_k vk ,且点 v i − 1 v_{i-1} vi−1 与点 v i v_i vi 之间的距离为 e i e_i ei ,则这条 Hamilton 路径的长度为 e 1 ⊕ e 2 ⊕ ⋯ ⊕ e k e_1\oplus e_2\oplus\cdots\oplus e_k e1⊕e2⊕⋯⊕ek ;其中, e i = v i − 1 ⊕ v i e_i=v_{i-1}\oplus v_i ei=vi−1⊕vi 。于是,路径的长度为: ( v 0 ⊕ v 1 ) ⊕ ( v 1 ⊕ v 2 ) ⊕ ⋯ ⊕ ( v k − 1 ⊕ v k ) (v_0\oplus v_1)\oplus(v_1\oplus v_2)\oplus\cdots\oplus(v_{k-1}\oplus v_k) (v0⊕v1)⊕(v1⊕v2)⊕⋯⊕(vk−1⊕vk),即 v 0 ⊕ ( v 1 ⊕ v 1 ) ⊕ ( v 2 ⊕ v 2 ) ⊕ ⋯ ⊕ ( v k − 1 ⊕ v k − 1 ) ⊕ v k v_0\oplus(v_1\oplus v_1)\oplus(v_2\oplus v_2)\oplus\cdots\oplus(v_{k-1}\oplus v_{k-1})\oplus v_k v0⊕(v1⊕v1)⊕(v2⊕v2)⊕⋯⊕(vk−1⊕vk−1)⊕vk 。
根据异或运算的规则,可以得到异或运算的一个基本规律: a ⊕ a = 0 a\oplus a=0 a⊕a=0 。于是,上式可以化简为 v 0 ⊕ v k v_0\oplus v_k v0⊕vk 。可见,这个值只与起止点有关,而与中间路过的点无关。
于是,在编号为 0 , 1 , 2 , ⋯   , n 0,1,2,\cdots,n 0,1,2,⋯,n 的图中, u → v u\rightarrow v u→v 的 Hamilton 路径的长度为 u ⊕ v u\oplus v u⊕v 。本题的答案即是求解 u ⊕ v u\oplus v u⊕v 的最大值,其中 0 ≤ u , v ≤ n 0\le u,v\le n 0≤u,v≤n ,且 u ≠ v u\ne v u̸=v 。此时,依靠枚举,似乎已经可以解决这个问题了。但是在 1 ≤ n ≤ 1 0 5 1\le n\le 10^5 1≤n≤105 的数据范围下,将可能会 TLE 。
以下考虑从数学上更为高效地求解这个问题。
考虑是否可以将 n n n 的所有可用的二进制位(即最高的 ′ 1 ′ '1' ′1′ 位以下的二进制位)均变为 1 1 1 。不妨设变换后的这个数为 S S S 。设 n n n 的最高可用位数为 b − 1 b-1 b−1 ,则 S = 2 b − 1 S=2^b-1 S=2b−1 。考虑是否存在 u u u 和 v v v ,使得 u ⊕ v = S u\oplus v=S u⊕v=S。如果解存在,则 S S S 即为异或可以达到的最大值。
由于 0 ≤ u , v ≤ n 0\le u,v\le n 0≤u,v≤n ,且 S S S 的所有可用位均为 1 1 1 ,故 u + v = S u+v=S u+v=S 。这个解显然是存在的。
之后,考虑字典序最小化条件。为使得 u u u 的值尽可能小,则应当使得 v v v 的值尽可能大。于是 u u u 和 v v v 的一组解为 u = S − n u=S-n u=S−n 和 v = n v=n v=n 。由于 2 b − 1 ≤ n ≤ 2 b − 1 2^{b-1}\le n\le 2^b-1 2b−1≤n≤2b−1 ,故 u = S − n < 2 b − n ≤ 2 b − 1 ≤ n = v u=S-n<2^b-n\le 2^{b-1}\le n=v u=S−n<2b−n≤2b−1≤n=v ,即 u < v u<v u<v 。
之前提到,路径长度与中间经过的点无关,则将中间经过的点从小到大排列即可。
参考程序如下:
#include
int main(int argc, char* argv[])
{
int n;
scanf("%d", &n);
int bit = 0;
for (; n >> bit; bit++) {}
int ans = (1 << bit) - 1;
printf("%d\n", ans);
int u = ans - n;
int v = n;
printf("%d ", u);
for (int i = 0; i <= n; i++) {
if (i != u && i != v) {
printf("%d ", i);
}
}
printf("%d\n", v);
return 0;
}
首先我们把题目翻译成人话,设有数列
k 0 , k 0 ⋯   , k 0 , k 1 , k 1 , ⋯   , k 1 , k 2 , k 2 , ⋯   , k 2 , ⋯   , k n − 1 , k n − 1 , ⋯ k n − 1 k^0,k^0\cdots ,k^0,k^1,k^1,\cdots ,k^1,k^2,k^2,\cdots,k^2,\cdots ,k^{n-1},k^{n-1},\cdots k^{n-1} k0,k0⋯,k0,k1,k1,⋯,k1,k2,k2,⋯,k2,⋯,kn−1,kn−1,⋯kn−1
对 于 自 然 数 m ( 1 ≤ m ≤ k n − 1 ) , 用 数 列 中 不 同 位 置 的 某 些 项 之 和 来 表 示 m 的 方 法 数 记 为 a m , 设 数 列 各 项 和 为 S 对于自然数m(1\leq m\leq k^n-1),用数列中不同位置的某些项之和来表示m的方法数记为a_m,设数列各项和为S 对于自然数m(1≤m≤kn−1),用数列中不同位置的某些项之和来表示m的方法数记为am,设数列各项和为S
请 你 求 出 a 1 + a 2 + a 3 + ⋯ + a S 请你求出a_1+a_2+a_3+\cdots+a_S 请你求出a1+a2+a3+⋯+aS
注 意 到 k 0 + k 0 + ⋯ + k 0 + k 1 + k 1 + ⋯ + k 1 + k 2 + k 2 + ⋯ + k 2 + ⋯ + k n − 1 + k n − 1 + ⋯ + k n − 1 = k n − 1 注意到k^0+k^0+\cdots+k^0+k^1+k^1+\cdots+k^1+k^2+k^2+\cdots+k^2+\cdots +k^{n-1}+k^{n-1}+\cdots+k^{n-1}=k^n-1 注意到k0+k0+⋯+k0+k1+k1+⋯+k1+k2+k2+⋯+k2+⋯+kn−1+kn−1+⋯+kn−1=kn−1
设 P n = a 1 + a 2 + ⋯ + a k n − 1 设P_n=a_1+a_2+\cdots+a_{k^n-1} 设Pn=a1+a2+⋯+akn−1
对于(k-1)(n+1)项数列
k 0 , k 0 ⋯   , k 0 , k 1 , k 1 , ⋯   , k 1 , k 2 , k 2 , ⋯   , k 2 , ⋯   , k n − 1 , k n − 1 , ⋯ k n − 1 , k n , k n , ⋯   , k n k^0,k^0\cdots ,k^0,k^1,k^1,\cdots ,k^1,k^2,k^2,\cdots,k^2,\cdots ,k^{n-1},k^{n-1},\cdots k^{n-1},k^n,k^n,\cdots,k^n k0,k0⋯,k0,k1,k1,⋯,k1,k2,k2,⋯,k2,⋯,kn−1,kn−1,⋯kn−1,kn,kn,⋯,kn
设 用 前 面 ( k − 1 ) n 项 表 示 1 至 k n − 1 的 自 然 数 方 法 之 和 为 P n , 若 自 然 数 1 ≤ m ≤ ( k n − 1 ) , 设用前面(k-1)n项表示1至k^n-1的自然数方法之和为P_n,若自然数1\leq m\leq(k^n-1), 设用前面(k−1)n项表示1至kn−1的自然数方法之和为Pn,若自然数1≤m≤(kn−1),
m 用 数 列 中 前 n ( k − 1 ) 项 表 示 有 a m 种 方 法 , 则 自 然 数 m + k n 用 上 述 数 列 表 示 就 有 C ( k − 1 , 1 ) ∗ a m 种 方 法 , ⋯ m用数列中前n(k-1)项表示有a_m种方法,则自然数m+k^n用上述数列表示就有C(k-1,1)*a_m种方法,\cdots m用数列中前n(k−1)项表示有am种方法,则自然数m+kn用上述数列表示就有C(k−1,1)∗am种方法,⋯
m + 2 ∗ k n 有 C ( k − 1 , 2 ) ∗ a m 种 方 法 ⋯ m + ( k − 1 ) × k n 用 上 述 数 列 表 示 有 C ( k − 1 , k − 1 ) ∗ a m 种 方 法 m+2*k^n有C(k-1,2)*a_m种方法\cdots m+(k-1)\times k^n用上述数列表示有C(k-1,k-1)*a_m种方法 m+2∗kn有C(k−1,2)∗am种方法⋯m+(k−1)×kn用上述数列表示有C(k−1,k−1)∗am种方法
此 外 易 得 a k n = C ( k − 1 , 1 ) , a 2 × k n = C ( k − 1 , 2 ) , ⋯   , a ( k − 1 ) k n = C ( k − 1 , k − 1 ) 此外易得a_{k^n}=C(k-1,1),a_{2\times k^n}=C(k-1,2),\cdots,a_{(k-1)k^n}=C(k-1,k-1) 此外易得akn=C(k−1,1),a2×kn=C(k−1,2),⋯,a(k−1)kn=C(k−1,k−1)
所 以 P n + 1 = P n + P n ∗ ( 2 k − 1 − 1 ) + ( 2 k − 1 − 1 ) 所以P_{n+1}=P_n+P_n*(2^{k-1}-1)+(2^{k-1}-1) 所以Pn+1=Pn+Pn∗(2k−1−1)+(2k−1−1)
再 算 出 P 1 = C ( k − 1 , 1 ) + C ( k − 1 , 2 ) + ⋯ + C ( k − 1 , k − 1 ) = 2 k − 1 − 1 ( 以 上 C 为 组 合 数 公 式 ) 再算出P_1=C(k-1,1)+C(k-1,2)+\cdots+C(k-1,k-1)=2^{k-1}-1(以上C为组合数公式) 再算出P1=C(k−1,1)+C(k−1,2)+⋯+C(k−1,k−1)=2k−1−1(以上C为组合数公式)
推 出 P n = 2 n ( k − 1 ) − 1 , 不 难 看 出 该 数 的 二 进 制 表 示 为 连 续 的 n ∗ ( k − 1 ) 个 ′ 1 ′ 推出P_n=2^{n(k-1)}-1,不难看出该数的二进制表示为连续的n*(k-1)个'1' 推出Pn=2n(k−1)−1,不难看出该数的二进制表示为连续的n∗(k−1)个′1′
所以以下就是本题的代码:
for (int i = 1; i <= n*(k-1); i++)
printf("1");
SAuppp(ljp):
当K = 3,有N种衣服那么穿衣状态就可以用长度为N的三进制数表示
比如N为3
那么搭配方案就是有(除去000)
001 002 010 011 012 020 021 022
100 101 102 110 111 112 120 121 122
200 201 202 210 211 212 220 221 222
26种(三进制下的1到 3 N − 1 3^N-1 3N−1)
那么注意到当某一位是0 或 2 ,那就是两件全不穿 或者全穿 (方案数*1
如果某一位是1 , 那就有两种可能 : 穿这一种的第一件, 或者是另外一件 (方案数*2
举个栗子: 210这个状态 , 就有2种表示方式( 1 ∗ 2 ∗ 1 1*2*1 1∗2∗1)(第一种两件都穿 第二种穿第一件 第三种都不穿)(第一种两件都穿 第二种穿第二件 第三种都不穿)
而 112 就有4种方式 ( 2 ∗ 2 ∗ 1 2*2*1 2∗2∗1) (略)
然后, 运用高中数学知识
答案就应该是 : 枚举1的数量 , 再组合一下1的位置; 再枚举剩下的0的数量,在组合0的位置; 剩下的就全是2
然后写出来就是
∑ i = 0 N [ C N i ∗ 2 i ∗ ∑ j = 0 N − i ( 1 j ∗ 1 ( N − i ) − j ) ] \sum_{i = 0}^{N} [C_{N}^{i} * 2^i * \sum_{j = 0}^{N - i} (1^j * 1^{(N-i)-j})] i=0∑N[CNi∗2i∗j=0∑N−i(1j∗1(N−i)−j)]
这个式子用二项式展开化简一下
∑ i = 0 N [ C N i ∗ 2 i ∗ 2 N − i ] = 4 N \sum_{i = 0}^{N} [C_{N}^{i} * 2^i * 2^{N-i}] =4^N i=0∑N[CNi∗2i∗2N−i]=4N
再减去裸奔的情况 4 N − 1 4^N - 1 4N−1,要求输出二进制,那么就直接输出2N个1就完事了
当k = 4,同理
∑ i = 0 N C N i 3 i ∑ j = 0 N − i C N − i j 3 j ∑ k = 0 N − i − j C N − i − j k 1 k ∑ l = 0 N − i − j − k C N − i − j − k l 1 l \sum_{i = 0}^{N}C_N^i 3^i \sum_{j = 0}^{N - i}C_{N - i}^j3^j \sum_{k = 0}^{N - i -j}C_{N - i-j}^k 1^k \sum_{l = 0}^{N - i - j - k}C_{N - i - j - k}^l 1^l i=0∑NCNi3ij=0∑N−iCN−ij3jk=0∑N−i−jCN−i−jk1kl=0∑N−i−j−kCN−i−j−kl1l
二项式展开化简为 8 N 8^N 8N,再减去裸奔 2 3 N − 1 2^{3N} - 1 23N−1
k=5 略