这个题又因为
zz
z
z
错误调了蛮久
有个地方判边界的时候
cnta
c
n
t
a
搞成
n
n
了
这个题发现数据范围很小 考虑搜索
但是直接搜是过不了的
考虑折半搜索再来合并答案
这样走下去就有两种思路了
第一个是把前一半的结果用 hash_table h a s h _ t a b l e 存下来
后面搜索的时候直接找剩下的是多少就好了
但是用 std::map s t d :: m a p 实现会 MLE M L E
可能需要手写 下面是 map m a p 的代码
Codes
#include<cstdio>
#include<map>
using namespace std;
const int N = 10;
map<int, int> cnt;
int n, m, len, ans;
int k[N], p[N];
int qpow(int a, int x) {
register int ret = 1;
while(x) {
if(x & 1) ret *= a;
x >>= 1, a *= a;
}
return ret;
}
void dfs1(int x, int sum) {
if(x > len) return void(++ cnt[sum]);
for(register int i = 1; i <= m; ++ i)
dfs1(x + 1, sum + k[x] * qpow(i, p[x]));
}
void dfs2(int x, int sum) {
if(x > n) return void(ans += cnt[-sum]);
for(register int i = 1; i <= m; ++ i)
dfs2(x + 1, sum + k[x] * qpow(i, p[x]));
}
int main() {
scanf("%d%d", &n, &m);
len = n >> 1;
for(int i = 1; i <= n; ++ i)
scanf("%d%d", &k[i], &p[i]);
dfs1(1, 0); dfs2(len + 1, 0);
printf("%d\n", ans);
// cout << procStatus();
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
return 0;
}
换种思路 我们把前一半和后一半的所有状态都存下来
发现是求两边的和加起来等于一个数的方案数
可以用 Two point T w o p o i n t 直接搞 排序之后移动指针就好了 但是相同值的状态用乘法原理合并进答案
这样复杂度就是 O(nm2m) O ( n m 2 m ) 了
Codes
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 150 * 150 * 151;
int n, m, len, ans, cnta, cntb;
int a[N], b[N], k[N], p[N];
int qpow(int a, int x) {
register int ret = 1;
while(x) {
if(x & 1) ret *= a;
x >>= 1, a *= a;
}
return ret;
}
void dfs1(int x, int sum) {
if(x > len) return void(a[++ cnta] = sum);
for(register int i = 1; i <= m; ++ i)
dfs1(x + 1, sum + k[x] * qpow(i, p[x]));
}
void dfs2(int x, int sum) {
if(x > n) return void(b[++ cntb] = sum);
for(register int i = 1; i <= m; ++ i)
dfs2(x + 1, sum + k[x] * qpow(i, p[x]));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("codevs1735.in", "r", stdin);
freopen("codevs1735.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
len = n >> 1;
for(int i = 1; i <= n; ++ i)
scanf("%d%d", &k[i], &p[i]);
dfs1(1, 0); dfs2(len + 1, 0);
sort(a + 1, a + cnta + 1);
sort(b + 1, b + cntb + 1);
int l = 1, r = cntb;
while(l <= cnta) {
while(a[l] + b[r] > 0 && r > 1) -- r;
if(a[l] + b[r] == 0) {
int cnt1 = 1, cnt2 = 1;
while(b[r - 1] == b[r] && r > 1) -- r, ++ cnt1;
while(a[l + 1] == a[l] && l < cnta) ++ l, ++ cnt2;
ans += cnt1 * cnt2;
}
++ l;
}
printf("%d\n", ans);
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
return 0;
}