Jersey Number(SOS+小思维)
发布日期:2021-06-30 10:27:24 浏览次数:2 分类:技术文章

本文共 1334 字,大约阅读时间需要 4 分钟。

题意

给定一个字符串,求有多少对区间有至少一个相同的字符

其中 n < = 100000 n<=100000 n<=100000


暴力枚举不适合

但是如果把一段区间包含的状态看成一个 16 16 16位的二进制数

总共的状态就是 2 16 2^{16} 216

这样转化有一个好处,设当前区间的状态为 m a s k mask mask,那么所有 m a s k mask mask的子集都是和 m a s k mask mask有交集

那么首先预处理 a [ m a s k ] a[mask] a[mask]表示状态为 m a s k mask mask的有 a [ m a s k ] a[mask] a[mask]个区间

那么显而易见使用 S O S D P SOSDP SOSDP求出 f [ m a s k ] = ∑ i & m a s k = = i a i f[mask]=\sum\limits_{i\&mask==i}a_i f[mask]=i&mask==iai

然后因为所有的方案有 n 2 ∗ ( n − 1 ) 2 / 4 n^2*(n-1)^2/4 n2(n1)2/4种方案,减去所有不相交方案数即可

也就是 c n t [ i ] ∗ f [ ∼ i ] cnt[i]*f[\sim i] cnt[i]f[i]

其中 c n t [ i ] cnt[i] cnt[i]为状态为 i i i的区间, f [ ∼ i ] f[\sim i] f[i]是和 i i i无交集的区间

于是所有问题变成了预处理 a [ m a s k ] a[mask] a[mask],这个只需要使用查找下一个字母的手法就可以求解了

#include 
using namespace std;#define int long longconst int mod = 1e9+7;const int maxn = 1e5+10;const int mx = 1<<16;const int inf = 1e9;int t,n,ans,nxt[maxn][17],f[mx],a[maxn],cnt[mx];char s[maxn];int is(char w){
if( w>='0'&&w<='9' ) return w-'0'; return w-'A'+10;}signed main(){
cin >> t; while( t-- ) {
scanf("%s",s+1); n = strlen( s+1 ); for(int i=1;i<=n;i++) a[i] = is(s[i]); for(int i=0;i<=15;i++) nxt[n+1][i] = inf; for(int i=0;i
=1;i--) {
for(int j=0;j<=15;j++) nxt[i][j] = nxt[i+1][j]; nxt[i][a[i+1]] = i+1; } for(int i=1;i<=n;i++) {
int temp = 1<

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/112796421 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:CodeChef - COVERING Covering Sets(sosdp+[FWT或高妙的容斥])
下一篇:KOSARE(sosdp+巧妙容斥)

发表评论

最新留言

很好
[***.229.124.182]2024年04月08日 15时34分44秒