[luogu P3799] 妖梦拼木棒

该博客详细介绍了如何使用C++和组合数理论来解决luogu P3799题目的妖梦拼木棒问题。博主首先指出暴力求解无法通过,然后解析了题意,提出关键在于设立相等边长并利用组合数计算方案数。通过将数据存储在桶中,并考虑两种情况(边长相等和不相等),博主给出了O(n^2)复杂度的解决方案。最后,博主分享了对此题的感想。
摘要由CSDN通过智能技术生成

[luogu P3799] 妖梦拼木棒

题目描述

点击此处查看题目描述

解决过程

暴力不多阐述,很显然是无法AC的

解决此题需要用到组合数

思路

这道题要求拼成等边三角形,我们设三边长为 a , b , c a ,b ,c a,b,c a = b = c a = b = c a=b=c

由于是用四根拼成,那么其中必有两条边相等,在此我们设 a = b a = b a=b c = i + j c = i+j c=i+j,把数据存到桶里面,桶为 f f f

那么需要 f [ c ] > = 2 f[c] >= 2 f[c]>=2,此时如果 i = j = c / 2 i = j = c/2 i=j=c/2,根据组合数,那么新增的方案数为 C f [ i ] 2 ∗ C f [ c ] 2 C^2_{f[i]} * C^2_{f[c]} Cf[i]2Cf[c]2

i ! = j i != j i!=j时,根据乘法原理和组合数,新增的方案数为 f [ i ] ∗ f [ j ] ∗ C f [ c ] 2 f[i] * f[j] * C^2_{f[c]} f[i]f[j]Cf[c]2

于是可以用 O ( n 2 ) O(n^2) O(n2) 的复杂度AC此题

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXM = 1e3 * 5 + 10;
const int mod = 1e9 + 7;
int a[MAXM] ,n ,ans = 0 ,s ,t;
int C (int nn, int mm) {
 return nn * (nn - 1) >> 1;
}
int main () {
// freopen ("P3799_1.in","r",stdin);
// freopen ("P3799.out","w",stdout);
 scanf ("%d",&n);
 int x;
 for (int q = 1;q <= n;++ q) {
  scanf ("%d",&x);
  s = min (s ,x);
  t = max (t ,x);
  a[x] ++;
 }
 for (int q = s;q <= t;++ q) {
  if (a[q] > 1) {
   for (int i = s;i <= q / 2;++ i) {
    int j = q - i;
    if (a[i] && a[j]) {
     if (i != j) {
      ans += a[i] * a[j] * C (a[q] ,2);
      ans %= mod;
     }
     else if (i == j && a[j] >= 2) {
      ans += C (a[q] ,2) * C (a[i] ,2);
      ans %= mod;
     }
    }
    
   }
  }
 }
 printf ("%d\n",ans % mod);
 return 0;
}

感想

谢谢大家
——2020.9.13

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值