【省内训练2018-12-23】Counting

【思路要点】

  • 问题等价于求不定方程 ∑ i = 1 N a i x i = C \sum_{i=1}^{N}a_ix_i=C i=1Naixi=C 的非负整数解的数量。
  • 考虑将 C , x i C,x_i C,xi 用二进制表示,我们从高位向低位依次决策 x i x_i xi 的某一位是否为 1 1 1
  • 假设当前决策的是第 i i i 位,那么当前决策的 ∑ i = 1 N a i x i \sum_{i=1}^{N}a_ix_i i=1Naixi 应当为 2 i + 1 2^{i+1} 2i+1 的倍数,并且剩余的尚未决策的位置上即使全部为 1 1 1 ,其总和也不会超过 2 ∗ 2 i ∗ ∑ i = 1 N a i 2*2^i*\sum_{i=1}^{N}a_i 22ii=1Nai
  • 因此,记 d p i , j , k dp_{i,j,k} dpi,j,k 表示决策到第 i i i 位,第 j j j 个数, ⌊ C − ∑ i = 1 N a i x i 2 i ⌋ = k \lfloor\frac{C-\sum_{i=1}^{N}a_ix_i}{2^i}\rfloor=k 2iCi=1Naixi=k 的方案数,由上面的推理, k > 2 ∗ ∑ i = 1 N a i k>2*\sum_{i=1}^{N}a_i k>2i=1Nai 的状态不会对答案产生贡献,不计之。
  • 时间复杂度 O ( N 2 ∗ M a x { s i } ∗ L o g C ) O(N^2*Max\{s_i\}*LogC) O(N2Max{si}LogC)

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 55;
const int MAXM = 505;
const int MAXS = 5e4 + 5;
const int P = 1e9 + 7;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
char s[MAXM];
int n, m, a[MAXN], bits[MAXM];
int dp[2][MAXN][MAXS];
void convert() {
	int len = strlen(s + 1);
	for (int i = 1; i <= len; i++)
		s[i] = s[i] - '0';
	reverse(s + 1, s + len + 1);
	while (len != 0) {
		bits[++m] = s[1] & 1, s[1] -= bits[m];
		for (int i = len; i >= 1; i--) {
			if (s[i] & 1) s[i - 1] += 10;
			s[i] /= 2;
		}
		while (len && s[len] == 0) len--;
	}
}
void update(int &x, int y) {
	x += y;
	if (x >= P) x -= P;
}
int main() {
	freopen("counting.in", "r", stdin);
	freopen("counting.out", "w", stdout);
	scanf("%d %s", &n, s + 1);
	int sum = 0;
	for (int i = 1; i <= n; i++)
		read(a[i]), sum += a[i];
	convert();
	dp[m & 1][0][1] = 1;
	for (int i = m, now = m & 1, dest = now ^ 1; i >= 1; i--, swap(now, dest)) {
		for (int j = 1; j <= n; j++)
		for (int k = 0; k <= 2 * sum; k++) {
			update(dp[now][j][k], dp[now][j - 1][k]);
			if (k + a[j] <= 2 * sum) update(dp[now][j][k], dp[now][j - 1][k + a[j]]);
		}
		memset(dp[dest], 0, sizeof(dp[dest]));
		for (int k = 0; k <= sum; k++)
			if (k * 2 + bits[i - 1] <= 2 * sum) update(dp[dest][0][k * 2 + bits[i - 1]], dp[now][n][k]); 
	}
	printf("%d\n", dp[1][n][0]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
boosting-crowd-counting-via-multifaceted-attention是一种通过多方面注意力提升人群计数的方法。该方法利用了多个方面的特征来准确估计人群数量。 在传统的人群计数方法中,往往只关注人群的整体特征,而忽略了不同区域的细节。然而,不同区域之间的人群密度可能存在差异,因此细致地分析这些区域是非常重要的。 该方法首先利用卷积神经网络(CNN)提取图像的特征。然后,通过引入多个注意力机制,分别关注图像的局部细节、稀疏区域和密集区域。 首先,该方法引入了局部注意力机制,通过对图像的局部区域进行加权来捕捉人群的局部特征。这使得网络能够更好地适应不同区域的密度变化。 其次,该方法采用了稀疏区域注意力机制,它能够识别图像中的稀疏区域并将更多的注意力放在这些区域上。这是因为稀疏区域往往是需要重点关注的区域,因为它们可能包含有人群密度的极端变化。 最后,该方法还引入了密集区域注意力机制,通过提取图像中人群密集的区域,并将更多的注意力放在这些区域上来准确估计人群数量。 综上所述,boosting-crowd-counting-via-multifaceted-attention是一种通过引入多个注意力机制来提高人群计数的方法。它能够从不同方面细致地分析图像,并利用局部、稀疏和密集区域的特征来准确估计人群数量。这个方法通过考虑人群分布的细节,提供了更精确的人群计数结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值