题解:P3447 [POI 2006] KRY-Crystals
P3447 [POI 2006] KRY-Crystals
简要题意: 求满足
解法:
考虑一个类似数位
这启发我们考虑这样一种方法:枚举位
如果有
用
-
\mathrm{bit}(m_i)=0 那么
a_i 仅能取到\mathrm{bit}(a_i)=0 ,一定顶到上界,所以这里不会发生脱离上界的跃迁,考虑方案数的贡献,由于顶到上界了,并且比k 高的位也是顶到上界点,所以此处需要限定a_i 后面的位不能超过m_i ,方案数就是\mathrm{msk}(m_i)+1 。于是得到转移:f_{i,x,y}\leftarrow f_{i-1,x,y}\times [\mathrm{msk}(m_i)+1] -
\mathrm{bit}(m_i)=1 -
\mathrm{bit}(a_i)=0
于是
a_i 就脱离上界了,由于要将贡献算在第一个脱离上界的位置,如果之前没有脱离上界的数,那么a_i 是要用来确定异或和位的0 ,是唯一确定,所以有转移f_{i,x,1}\leftarrow f_{i,x,0} 。否则说明已经存在一个数来保证异或和,这个数比k 低的位都可以随便选,总共有2^k 中方案,得到f_{i,x,1}\leftarrow f_{i,x,1}\times 2^k ,总结到f_{i,x,1}\leftarrow f_{i,x,0} \\ f_{i,x,1}\leftarrow f_{i,x,1}\times 2^k -
\mathrm{bit}(a_i)=1
那么
a_i 依旧顶着上界,类似的:f_{i,x,y}\leftarrow f_{i-1,x\oplus 1,y}\times [\mathrm{msk}(m_i)+1] -
于是完成了,总方案数就是
注意细节:
- 如果
\displaystyle\bigoplus_{i=1}^{n} m_i=0 ,那么每一位都不脱离上界是可行的,此时不会被统计到,答案要记上1 。 - 由于要求
a_i 不全为0 ,答案要舍弃全0 ,减去1 。
:::info[代码]
#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
typedef unsigned long long ull;
const int N=55;
int n;
int m[N];
ull f[N][2][2];
signed main()
{
cin >> n;
int msk=0;
for (int i=1;i<=n;i++)
{
cin >> m[i];
msk^=m[i];
}
ull ans=0;
if (!msk) ans++;
for (int k=31;~k;k--)
{
if ((msk>>(k+1))&1) break;
int bit=(1ll<<k)-1;
memset(f,0,sizeof(f));
f[0][0][0]=1;
for (int i=1;i<=n;i++)
{
int cur=(m[i]>>k)&1;
if (cur)
{
for (int x=0;x<2;x++)
{
f[i][x][1]+=f[i-1][x][0];
f[i][x][1]+=f[i-1][x][1]*(1ll<<k);
}
}
for (int x=0;x<2;x++)
{
for (int y=0;y<2;y++)
{
ull cof=(m[i]&bit)+1;
f[i][x][y]+=f[i-1][x^cur][y]*cof;
}
}
}
ans+=f[n][0][1];
}
cout << ans-1 << "\n";
return 0;
}
:::