今天的t2t3能打出来80分的暴力都好满足啊QwQ。(%%%$idy$

今天的签到题,做的时候一眼就看出性质叻qwq。大于11的所有数分解合数都可以用4、6、9表示,乱搞搞就可以了。

#include<iostream>
#include<cstdio>
using namespace std; void read ( int &x ) {
x = ; char ch = getchar ( );
while ( ch > '' || ch < '' ) ch = getchar ( );
while ( ch >= '' && ch <= '' ) {
x = x * + ch - ''; ch = getchar ( );
}
} int main ( ) {
freopen ( "split.in", "r", stdin );
freopen ( "split.out", "w", stdout );
int T;
scanf ( "%d", &T );
while ( T -- ) {
int n;
read ( n );
int t = n / , qwq = n % ;
if ( t < ) {
printf ( "-1\n" );
} else if ( t % == && qwq == ) {
printf ( "%d\n", t / );
} else if ( t % == && qwq ) {
if ( n == ) {
printf ( "-1\n" );
} else if ( t <= ) {
printf ( "1\n" );
} else printf ( "%d\n", t / - );
} else if ( t % && qwq == ) {
printf ( "%d\n", t / );
} else if ( t % && qwq ) {
if ( n < ) {
printf ( "-1\n" );
} else {
printf ( "%d\n", ( t - ) / + );
}
}
}
return ;
}

$yuli$(%%%a掉的一道神题!(至今不理解dalao的思维方式QwQ

好不容易搞懂了$idy$的解释!是一种很巧妙的理解方法。我们把所有的点的横纵坐标之间连边,构成了下图所示的多个连通图:

实际上图中的每条边就相当于每个点了,每条边可以选择管辖一个点,就是原问题中的一条直线。我们把所有有关系的点建成如上图所示(区分一下x和y坐标),可以发现,不在同一个联通块之间的点(原图中的直线)就永远不会互相影响。所以我们只用计算每个联通块的方案数,用乘法原理即可。

每个联通块又分为两种情况,第一种是如上图的树形结构。【一下的边和点都指建出的新图中的边和点】即边数小于点数,最大的覆盖只能是边数。如下图:

最少都会不能覆盖到一个点。又因为每条边我们可以选择管辖点或者不管辖,所以设点数是$size$,$size-1$的所有子集都可以达到。此时方案数为$2^{size-1}$。

另一种情况,就是样例二中多个点相互重叠影响,如下图:

我们可以发现,只要出现了这种情况,整个点集都可以被覆盖,如下图:

而所有方案的子集也都能达到,所以此时的方案数是$2^{size}$。

有了以上的理解,我们就可以愉快地建图计算辣~维护一个并查集的$size$,表示当前联通块的点数,建边过后跑$dfs$,标记联通块中的点并判断是否有环。答案累乘即可。【注意】原图中点的坐标需要离散化。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std; const int mod = 1e9 + ; int n; ll mpow ( ll a, ll b ) {
ll ans = ;
for ( ; b; b >>= , a = a * a % mod )
if ( b & ) ans = ans * a % mod;
return ans;
} int stot, nex[], tov[], h[];
void add ( int u, int v ) {
tov[++stot] = v;
nex[stot] = h[u];
h[u] = stot;
} struct node {
int x, y;
} poi[]; bool vis[], flag;
void dfs ( int u, int f ) {
vis[u] = ;
for ( int i = h[u]; i; i = nex[i] ) {
int v = tov[i];
if ( v == f ) continue;
if ( vis[v] ) { flag = ; continue; }
dfs ( v, u );
}
} int fa[], siz[];
int find ( int x ) {
if ( fa[x] != x ) return fa[x] = find ( fa[x] );
return x;
} void unionn ( int x, int y ) {
int xx = find ( x ); int yy = find ( y );
fa[xx] = yy;
siz[yy] += siz[xx];
} ll x[], y[];
int main ( ) {
freopen ( "cross.in", "r", stdin );
freopen ( "cross.out", "w", stdout );
scanf ( "%d", &n );
for ( int i = ; i <= n; i ++ ) {
scanf ( "%I64d%I64d", &x[i], &y[i] );
poi[i].x = x[i]; poi[i].y = y[i];
}
sort ( x + , x + + n );
sort ( y + , y + + n );
int m = unique ( x + , x + + n ) - x - ;
int k = unique ( y + , y + + n ) - y - ;
for ( int i = ; i <= n; i ++ ) {
poi[i].x = lower_bound ( x + , x + + m, poi[i].x ) - x;
poi[i].y = lower_bound ( y + , y + + k, poi[i].y ) - y + n;
}
for ( int i = ; i <= n; i ++ ) {
int xx = poi[i].x, yy = poi[i].y;
fa[xx] = xx; fa[yy] = yy; siz[xx] = siz[yy] = ;
}
for ( int i = ; i <= n; i ++ ) {
int xx = poi[i].x, yy = poi[i].y;
add ( xx, yy );
add ( yy, xx );
if ( find ( xx ) != find ( yy ) )
unionn ( xx, yy );
}
ll ans = ;
for ( int i = ; i <= n; i ++ ) {
int xx = poi[i].x;
if ( !vis[xx] ) {
flag = ;
dfs ( xx, );
int size = siz[find ( xx )];
if ( flag ) {
ans = ans * mpow ( , (ll)size ) % mod;
} else {
ans = ans * ( mpow ( , (ll)size ) - ) % mod;
}
}
}
printf ( "%I64d", ans );
return ;
}

看了标程惊觉$string$这个容器真是强无敌啊QwQ!比开$char$数组多了很多很方便的操作!

然后回想起考场上自己乱搞搞的哈希和暴力合并,其实感觉思路没错,就是模拟合并的操作,但是没有发现两个串合并起来,只需要判断第一个串的尾和第二个串的头$k$个字符有没有贡献就可以了!整个串又丑又长塞不下aaaQwQ

至于上面的$k$,我们可以发现,因为每个原始串中最多有$100-k+1$个长度为$k$的子串,原始最多有$100*(100-k+1)$个长度为k的子串,而每次合并两个串,最多只会增加$k$个长度为$k$的子串,最多增加$100*k$个,所以自始至终最多只会有$100*(100-k+1)+100*k$个长度为$k$的子串。而总子串数是$<=2^k$的,解出来$k<=13$(实际上11完全够了qwq。$k$非常小,我们可以把所有长度$1-11$的01串全部处理出来存在一个$stat$字符串组里面。

每次合并串的时候,我们只需要长度22就够了,所以截取前后即可。

定义$bool$数组$dp[i][j]$表示第$i$个串中是否存在我们预处理出来的第$j$个$stat$串,更新就是用$string$中的取子串操作$substr$取出两个组合的子串判断即可,如果是前$n$个串初始串暴力判断即可。

处理完$dp$数组后,直接所有串扫一遍,只要有一个长度为$p$的子串不存在,$p$就一定不是最后的解。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int L = ; int n, m, opt;
string str[];
string stat[];
int son[][], dp[][]; void init ( ) {
for ( int l = ; l <= L; l ++ ) {
for ( int i = ; i < ( << l ); i ++ ) {
++opt;
string &s = stat[opt];
s.resize ( l );
for ( int j = ; j < l; j ++ )
s[j] = ( char ) ( '' + ( ( i >> j ) & ) );
}
}
} string merge ( string a, string b ) {
string c;
for( int i = ; i < a.size ( ); i ++ )
c.push_back( a[i] );
for( int i = ; i < b.size ( ); i ++ )
c.push_back( b[i] );
if ( c.length ( ) > * L ) {
string cc;
for ( int i = ; i < L; i ++ )
cc.push_back ( c[i] );
for ( int i = ; i < L; i ++ )
cc.push_back ( c[c.length ( )-L+i] );
return cc;
} else return c;
} int main ( ) {
freopen ( "string.in", "r", stdin );
freopen ( "string.out", "w", stdout );
ios :: sync_with_stdio ( );
init ( );
cin >> n;
for ( int i = ; i <= n; i ++ )
cin >> str[i];
cin >> m;
for ( int i = ; i <= m; i ++ ) {
int a, b;
cin >> a >> b;
str[i+n] = merge ( str[a], str[b] );
son[i+n][] = a;
son[i+n][] = b;
}
for ( int i = ; i <= n + m; i ++ ) {
if ( i <= n ) {
for ( int j = ; j <= opt; j ++ )
for ( int k = ; k + stat[j].size ( ) <= str[i].size ( ); k ++ )
if ( str[i].substr ( k, stat[j].size ( ) ) == stat[j] ) {
dp[i][j] = ; break;
}
} else {
int a = son[i][];
int b = son[i][];
for ( int j = ; j <= opt; j ++ ) {
dp[i][j] = ( dp[a][j] || dp[b][j] );
if ( dp[i][j] ) continue;
for ( int l = ; l < stat[j].size ( ); l ++ ) {
if ( l > str[a].length ( ) || stat[j].length ( ) - l > str[b].length ( ) ) continue;
if ( str[a].substr ( str[a].length ( ) - l, l ) + str[b].substr ( , stat[j].length ( ) - l ) == stat[j] ) {
dp[i][j] = ; break;
}
}
}
}
}
for ( int i = n + ; i <= n + m; i ++ ) {
bool ok[L+];
memset ( ok, , sizeof ( ok ) );
for ( int j = ; j <= opt; j ++ ) {
if ( !dp[i][j] ) {
ok[stat[j].length ( )] = ;
}
}
for ( int k = L; k >= ; k -- )
if ( ok[k] ) {
printf ( "%d\n", k );
break;
}
}
return ;
}

【8.22校内测试】【数学】【并查集】【string】的更多相关文章

  1. [CSP-S模拟测试]:x(数学+并查集)

    题目背景 $\frac{1}{4}$遇到了一道水题,叒完全不会做,于是去请教小$D$.小$D$都没看就切掉了这题,嘲讽了$\frac{1}{4}$一番就离开了.于是,$\frac{1}{4}$只好来问 ...

  2. 【9.22校内测试】【可持久化并查集(主席树实现)】【DP】【点双联通分量/割点】

    1 build1.1 Description从前有一个王国,里面有n 座城市,一开始两两不连通.现在国王将进行m 次命令,命令可能有两种,一种是在u 和v 之间修建道路,另一种是询问在第u 次命令执行 ...

  3. 【11.1校内测试】【快速幂DP】【带权并查集】【模拟】

    Solution $jzy$大佬用了给的原根的信息,加上矩阵快速幂150行QAQ 然而$yuli$大佬的做法不仅好懂,代码只有50行! 快速幂的思想,把m看成要组成的区间总长度,每次将两段组合得到新的 ...

  4. 【NOIP模拟_54测试】【并查集】【二进制】【搜索】【区间序列类】

    第一题 Mushroom的序列 大意: 给一个序列,求一段连续最长区间满足:最多改变一个数,使得区间是严格的上升子序列. 解: 直接扫描一遍,记一个最长上升子序列编号.然后从每一个编号为1 的点来判断 ...

  5. HDU 5441 Travel (并查集+数学+计数)

    题意:给你一个带权的无向图,然后q(q≤5000)次询问,问有多少对城市(城市对(u,v)与(v,u)算不同的城市对,而且u≠v)之间的边的长度不超过d(如果城市u到城市v途经城市w, 那么需要城市u ...

  6. BZOJ 2303: [Apio2011]方格染色 [并查集 数学!]

    题意: $n*m:n,m \le 10^6$的网格,每个$2 \times 2$的方格必须有1个或3个涂成红色,其余涂成蓝色 有一些方格已经有颜色 求方案数 太神了!!!花我三节课 首先想了一下只有两 ...

  7. 2019.01.22 zoj3583 Simple Path(并查集+枚举)

    传送门 题意简述:给出一张图问不在从sss到ttt所有简单路径上的点数. 思路: 枚举删去每个点然后把整张图用并查集处理一下,同时不跟sss和ttt在同一个连通块的点就是满足要求的点(被删去的不算). ...

  8. 2019.01.22 uoj#14. 【UER #1】DZY Loves Graph(并查集)

    传送门 题意简述: 要求支持以下操作: 在a与b之间连一条长度为i的边(i是操作编号):删除当前图中边权最大的k条边:表示撤销第 i−1次操作,保证第1次,第i−1 次不是撤回操作. 要求在每次操作后 ...

  9. P3043 [USACO12JAN]牛联盟(并查集+数学)

    (m<n<=1e5,有重边) 题目表述有问题..... 给定一张图(不一定联通),每条边可以选择连接的两个点之一,剩余的点可以自己成对,问方案数. 一开始是真的被吓到了....觉得可写性极 ...

随机推荐

  1. 带你优雅的使用 icon

    前言 本篇文章其实陆陆续续写了快半年,主体部分写好了很久了,但由于种种原因一直没有发布.首先来说说写这篇文章的主要初衷是:在做前端后台项目的时候经常会用到很多 icon 图标,刚开始还好,但随着项目的 ...

  2. Msql中的触发器

    解发器 当执行某种操作时解发的行为. 比如, 当表变动时触发的动作. 像商城订单, 当下单时, 库存减少. 语法: create trigger trigger_name after/befor in ...

  3. 作为一个新手的Oracle(DBA)学习笔记【转】

    一.Oracle的使用 1).启动 *DQL:数据查询语言 *DML:数据操作语言 *DDL:数据定义语言 DCL:数据控制语言 TPL:事务处理语言 CCL:指针控制语言 1.登录 Win+R—cm ...

  4. 8.Python3标准库--数据持久存储与交换

    ''' 持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区. 标准库包含很多模块可以处理不同情况下的这两个方面 有两个模块可以将对象转换为一 ...

  5. go语言入门(三)

    条件语句 go语言的条件语句结构如下: go语言的条件语句和其他语言类似.简单列举下: 1.if 语句,布尔表达式不需要括号 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 2 ...

  6. C语言实现knn

    以后写代码一定要谨慎,提高代码的正确率. /*************************************** * 1.初始化距离为最大值 * 2.计算未知样本和每个训练样本的距离为dis ...

  7. 以太坊go-ethereum客户端JSON-RPC API调用(一)

    前几篇博客主要介绍了go-ethereum客户端不同环境的搭建,今天这篇博客是建立在前几排博客的基础上.当搭建完成之后,我们可以通过各种方式与节点进行交互(JavaScript Console.JSO ...

  8. python中__dict__与dir()的区别

    在python中__dict__与dir()都可以返回一个对象的属性,区别在于: __dict__是对象的一个属性,而dir()是一个built-in的方法: __dict__返回一个对象的属性名和值 ...

  9. naive cube implementation in python

    这篇论文中提到的naive cube算法的实现,python写出来真的就和伪代码差不多=.= 输入大约长这样,依次是 index userid country state city topic cat ...

  10. centos7 开放端口号

    firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --reload