codeforces ASC28J 三元环计数

博客介绍了如何利用bitset优化解决codeforces ASC28J问题中的三元环计数。通过存储每个节点的出边和入边,暴力枚举并进行位运算,将原本的时间复杂度从O(n^3)优化到O(n^3*ω),其中ω为bitset的位数。最终答案需要除以3。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面

这个题也不是很难,就是个一般的三元环计数

今天用一种奇怪的做法 bitset b i t s e t 来优化

bitset b i t s e t 是个很好用的东西 类似于一个二进制数 但是时间和空间消耗都很小

它大概有以下操作

1. 1. 所有的位运算,例如 <<,>>,|, << , >> , | , ⊕ 还有&运算

2. 2. 一些相关的函数

#include<iostream>
#include<bitset>

std::bitset<233> f;

int main() {
    f.size(); //bitset的大小 在这里就是233
    f.count(); //bitset 中二进制1的个数
    f.set(); //所有位都设为1
    f.reset(); //所有的位都设为0
    f.set(u); //把第u位设为1
    f.reset(u); //把第u位设为0
    f.any(); //是否存在一位是1
    f[x]; // 访问第x位的元素
    f.flip(); //取反所有位
    f.flip(x); //取反第x位
    f.to_ulong(); //转化为unsigned long 并返回
}

反正这个东西自带一个 1ω 1 ω 的常数,可以优化一些过不了的东西

64 64 位的机器上 ω=64 ω = 64 这样子 n3 n 3 的算法就可以优化到 O(n3ω) O ( n 3 ω ) 就能跑 n=1000 n = 1000

这个题加上 bitset b i t s e t 的做法之后就可以直接跑最暴力的做法了

首先把每个点的出边和入边都用 bitset b i t s e t 存下来

然后暴力枚举两个点, a>b a − > b , 把 a a 的入边和b的出边进行与操作后里面 1 1 的个数加入答案就够了。

因为三元环每条边都被枚举到了一次 最后答案除个3就好了

记得开longlong

复杂度 O(n3ω) O ( n 3 ω )

Codes
#include<bits/stdc++.h>

using namespace std;

const int N = 1500 + 10;
bitset<N> in[N], out[N];
int a[N][N], ans;

int main() {
    freopen("triatrip.in", "r", stdin);
    freopen("triatrip.out", "w", stdout);
    int n; long long ans = 0; char c;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i) 
        for(int j = 1; j <= n; ++ j) {
            cin >> c;
            if(c == '+') {
                a[i][j] = 1; 
                out[i][j] = 1;
                in[j][i] = 1;
            }
        }
    for(int i = 1; i <= n; ++ i)
        for(int j = 1; j <= n; ++ j)
            if(a[i][j])
                ans += (out[j] & in[i]).count();
    cout << ans / 3 << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值