2018.12.26 考试(哈希,二分,状压dp)
T1
解题思路
发现有一个限制是每个字母都必须相等,那么就可以转化成首尾的差值相等,然后就可以求出\(k-1\)位的差值\(hash\)一下。\(k\)为字符集大小,时间复杂度为\(O(nk)\)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int MAXN = 100005;
const int mod = 131;
const ull base = 666623333;
const int MOD = 1e9+7;
int n,cnt,sum[MAXN][60];
char s[MAXN];
LL ans;
ull hsh[MAXN];
map<char,int> mp;
map<ull,int> SUM;
int main(){
    scanf("%d%s",&n,s+1);
    for(int i=1;i<=n;i++){
        if(!mp.count(s[i])) mp[s[i]]=++cnt;
        sum[i][mp[s[i]]]=1;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=cnt;j++)
            sum[i][j]+=sum[i-1][j];
    //for(int i=1;i<=n;i++)
        //for(int j=1;j<=cnt;j++)
            //printf("sum[%d][%d]=%d\n",i,j,sum[i][j]);
    for(int i=1;i<=n;i++){
        ull now=1;
        for(int j=2;j<=cnt;j++)
            now=now*base+(ull)(sum[i][j]-sum[i][j-1]+mod);
        hsh[i]=now;
        SUM[now]=SUM[now]+1;
    }
    hsh[0]=1;
    for(int j=1;j<cnt;j++)
        hsh[0]=hsh[0]*base+mod;
    SUM[hsh[0]]=SUM[hsh[0]]+1;
    for(int i=0;i<=n;i++){
        SUM[hsh[i]]=SUM[hsh[i]]-1;
        ans=(ans+SUM[hsh[i]])%MOD;
    }
    printf("%lld\n",ans);
    return 0;
}
T2
解题思路
二分一个时间,使得一对粒子的距离之和\(<=L\),然后重复\(k\)次,时间复杂度\(O(nklog(MAX)\)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 50005;
const double eps = 1e-6;
inline int rd(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return f?x:-x;
}
void out(int x){
	if(!x) return ;out(x/10);putchar('0'+x%10);
}
int n,L,k,Maxx[3],Maxy[3],ans[105][2];
bool visx[MAXN],visy[MAXN];
double disx[3],disy[3],now;
struct Data{
	int v,t;
}a[MAXN],b[MAXN];
inline bool check(int tmp,double lim){
	Maxx[1]=Maxx[2]=Maxy[1]=Maxy[2]=disx[1]=disx[2]=disy[1]=disy[2]=0;
	for(register int i=1;i<=n;i++){
		if(!visx[i] && a[i].t<=lim) {
			if((double)(lim-a[i].t)*a[i].v>disx[1]) {
				Maxx[2]=Maxx[1];disx[2]=disx[1];
				disx[1]=(double)(lim-a[i].t)*a[i].v;Maxx[1]=i;
			}
			else if((double)(lim-a[i].t)*a[i].v>disx[2]) Maxx[2]=i,disx[2]=(double)(lim-a[i].t)*a[i].v;
		}
		if(!visy[i] && b[i].t<=lim){
			if((double)(lim-b[i].t)*b[i].v>disy[1]){
				Maxy[2]=Maxy[1];disy[2]=disy[1];
				disy[1]=(double)(lim-b[i].t)*b[i].v;Maxy[1]=i;
			}
			else if(((double)(lim-b[i].t)*b[i].v>disy[2])) Maxy[2]=i,disy[2]=(double)(lim-b[i].t)*b[i].v;
		}
		if(disx[2]+disy[2]>=L) return 0;
	}
	if(!Maxx[1] || !Maxy[1]) return 1;
	if(disx[1]+disy[1]<L) return 1;
	if(disx[2]+disy[2]>=L) return 0;
	ans[tmp][0]=Maxx[1];ans[tmp][1]=Maxy[1];now=lim;
	return 0;
}
int main(){
	n=rd(),L=rd(),k=rd();double l,r,mid;
	for(register int i=1;i<=n;i++)
		a[i].t=rd(),a[i].v=rd();
	for(register int i=1;i<=n;i++)
		b[i].t=rd(),b[i].v=rd();
	for(register int i=1;i<=k;i++){
		l=now;r=1e9+2e8;
		while(r-l>=eps){
			mid=(l+r)/2;
			if(check(i,mid)) l=mid+eps;
			else r=mid-eps;
		}
		visx[ans[i][0]]=1;visy[ans[i][1]]=1;
		out(ans[i][0]),putchar(' '),out(ans[i][1]),putchar('\n');
	}
	return 0;
}
T3
解题思路
状压\(dp\),考场上脑抽了写了个\(2^{3^{质因数}}\)级别的垃圾做法。。正解十分玄学,前\(6\)位三进制状压表示每个质因数出现的次数,后\(21\)为二进制状压表示哪两个质因数不能同时出现,然后用\(map\)来存状态。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
#define int long long
using namespace std;
typedef long long LL;
const int MOD = 1e9+7;
const int poww[8] = {1,3,9,27,81,243,729,2187};
LL n;
int ans,a[55],cnt,num[55],ban[55];
map<int,int> mp;
map<int,int>::iterator it;
inline void init(){
	int x=n;
	for(LL i=2;i*i<=x;i++){
		if(x%i) continue;
		a[cnt]=i;
		while(!(x%i)) x/=i,num[cnt]++;
		cnt++;
	}
	if(x!=1) a[cnt]=x,num[cnt++]=1;
}
int get_new(int S,int now){
	int ret=S,bit=1;
	for(int i=0;i<cnt;i++){
		if((now&(1<<i)) && S/bit%3<2) ret+=bit;
		bit*=3;
	}
	for(int i=0;i<cnt;i++)
		for(int j=i+1;j<cnt;j++){
			if((now&(1<<i)) && ((S/poww[j])%3>0) && (!((S/bit)&1))) ret+=bit;
			else if((now&(1<<j)) && ((S/poww[i])%3>0) && (!((S/bit)&1))) ret+=bit;
			bit<<=1;
		}
	return ret;
}
inline int get_num(int S){
	int ret=1;
	for(int i=0;i<cnt;i++)
		if(S&(1<<i)) ret*=num[i],ret%=MOD;
	return ret;
}
signed main(){
	scanf("%lld",&n);int kk=0;
	init();it=mp.insert(make_pair(0,1)).first;
	while(it!=mp.end()){kk++;
		ans+=it->second;ans%=MOD;
		int tmp=it->first,now=0,tot=0,flag,k;
		for(int i=0;i<cnt;i++){
			if(tmp%3<2) now|=(1<<i);
			tmp/=3;
		}
		for(int i=0;i<cnt;i++)
			for(int j=i+1;j<cnt;j++){
				if(tmp&1) ban[++tot]=(1<<i)|(1<<j);
				tmp>>=1;
			}
		for(int i=now;i;i=(i-1)&now){
			flag=false;
			for(int j=1;j<=tot;j++)
				if((ban[j]|i)==i) {flag=true;break;}
			if(flag) continue;
			k=get_new(it->first,i);
			if(mp.find(k)==mp.end()) mp.insert(make_pair(k,0));
			mp[k]+=it->second*get_num(i)%MOD;mp[k]%=MOD;
		}
		it++;
	}
	printf("%lld\n",(ans-1+MOD)%MOD);
	return 0;
}
2018.12.26 考试(哈希,二分,状压dp)的更多相关文章
- 2018.09.22 牧场的安排(状压dp)
		描述 农民 John 购买了一处肥沃的矩形牧场,分成M*N(1 <= M <= 12; 1 <= N <= 12)个 格子.他想在那里的一些格子中种植美味的玉米.遗憾的是,有些 ... 
- hdu 3681(bfs+二分+状压dp判断)
		题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 思路:机器人从出发点出发要求走过所有的Y,因为点很少,所以就能想到经典的TSP问题.首先bfs预 ... 
- 洛谷P4363 [九省联考2018]一双木棋chess  【状压dp】
		题目 菲菲和牛牛在一块n 行m 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束. 落子的规则是:一个格子可以落子当且仅当这个 ... 
- #12【BZOJ3003】LED BFS+状压DP
		题解: 看到区间修改先想一下差分 这题用差分是为了分析问题 现在的问题就变成了 原序列全为0,要使得特定的k个点变为1,每个操作改变x,y+1 然后我们会发现 对于二元组a,b我们要修改它,实际上是在 ... 
- 2018.10.17 NOIP模拟 管道(状压dp)
		传送门 状压dp好题. 怎么今天道道题都有点东西啊 对于今天题目神仙出题人先膜为上策:%%%%DzYoAk_UoI%%%% 设f[i][j]f[i][j]f[i][j]表示选取点的状态集合为iii,当 ... 
- 2018.09.08 poj1185 炮兵阵地(状压dp)
		传送门 状压dp经典题. 我们把每一行的状态压成01串. 预处理出每一行可能出现的状态,然后转移每个被压缩的状态的1的个数就行了. 注意当前行转移要考虑前两行的状态. 还要注意只有一行的情况. 代码: ... 
- 2018.09.08 NOIP模拟 division(状压dp)
		这么sb的题考场居然写挂了2233. 假设n=∏iaiki" role="presentation" style="position: relative;&qu ... 
- 2018.08.29 NOIP模拟 movie(状压dp/随机化贪心)
		[描述] 小石头喜欢看电影,选择有 N 部电影可供选择,每一部电影会在一天的不同时段播 放.他希望连续看 L 分钟的电影.因为电影院是他家开的,所以他可以在一部电影播放过程中任何时间进入或退出,当然他 ... 
- noi省选 [九省联考2018]一双木棋题解(状压dp)
		比浙江简单多了........ 题目转送:https://www.luogu.org/problemnew/show/P4363 分析: 我们注意到n和m都很小,考虑一下状压dp. 显然,棋子摆成的形 ... 
随机推荐
- 硬盘监控和分析工具:Smartctl
			https://linux.cn/article-4682-1.html Smartctl(S.M.A.R.T 自监控,分析和报告技术)是类Unix系统下实施SMART任务命令行套件或工具,它用于打印 ... 
- Network基础(三):网线的制作、交换机基本命令模式、交换机命令行基本配置、交换机的密码设置
			一.网线的制作 目标: 在常见的计算机网络中,网线主要用来连接计算机与交换机(或宽带路由器).交换机与交换机.交换机与路由器,以及需要连网的其他各种设备.网线的制作与测试是作为网络管理员的一个入门技能 ... 
- BZOJ 3105: [cqoi2013]新Nim游戏(线性基)
			解题思路 \(nim\)游戏先手必胜的条件是异或和不为\(0\),也就是说第一个人拿走了若干堆后不管第二个人怎么拿都不能将剩余堆的异或和变成\(0\).考虑线性基,其实就是每个数对线性基都有贡献,任何 ... 
- PAT 1042 Shuffling Machine (20 分)
			1042 Shuffling Machine (20 分) Shuffling is a procedure used to randomize a deck of playing cards. ... 
- spss-数据清洗-处理重复数据
			spss-数据清洗-处理重复数据 数据导入之后就需要对数据进行清洗.数据清洗主要是对多余重复的数据筛选清除,将缺失的数据补充完整,将错误的数据纠正或者删除.接下来操作如何将重复数据处理操作. 步骤一: ... 
- #include和前置声明(forward declaration)
			#include和前置声明(forward declaration) 1. 当不需要调用类的实现时,包括constructor,copy constructor,assignment opera ... 
- activiti7从act_ge_bytearray表中查询资源文件并保存到桌面文件夹中
			package com.zcc.activiti02; import org.activiti.engine.ProcessEngine;import org.activiti.engine.Proc ... 
- Linux(一)—— Linux环境搭建
			Linux环境搭建 一.虚拟机安装 1.下载地址 https://my.vmware.com/web/vmware/info/slug/desktop_end_user_computing/vmwar ... 
- Java DOM解析器 - 解析XML文档
			使用DOM的步骤 以下是在使用DOM解析器解析文档使用的步骤. 导入XML相关的软件包. 创建DocumentBuilder 从文件或流创建一个文档 提取根元素 检查属性 检查子元素 导入XML相关的 ... 
- datepicker时间选择弹窗
			准备工作 首先请到jqueryui.com官网下载datepicker插件代码,注意官网提供了整个jquery ui的所有插件下载,但是您可以选择其中几个用到的插件下载,本文中只用到datepicke ... 
