ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

noip模拟32

2021-08-07 21:32:40  阅读:170  来源: 互联网

标签:pp noip int 32 long 因子 mp maxm 模拟


\(\color{white}{\mathbb{山高而青云冷,池深而蛟穴昏,行以慎步,援以轻身,名之以:落石}}\)


pic.png

开题发现 \(t1\) 80分特别好写,于是先写了
但是这个做法没有任何扩展性,导致一直没有往正解的方向想

\(t3\) 看见有点的坐标,以为是计算几何,于是写完 \(t1\) 打了个暴力就看 \(t2\) 了
但事实证明 \(t2\) 的难度实际上是最大的,这次题目难度的判断又出现了严重的失误

A. Smooth

观察 B=2 的情况,发现排好序两因子的次数递增是没有规律的
可以把两个因子都开个队列,每次队里是单调递增的,所以队首是最小值
每次取出所有队首中的最小值,即使下一个排名的光滑数
然后运用类似线性筛的东西给每个大于其最小质因子的数加入其乘质数的值


B. Six

首先,要肯定这道题状态只统计每个质因子出现了几次是不行的,比如第一次插入一个6,那么2和3都被标记出现一次,当另一个6来时,发现其因子共出现两次而不能加入序列导致判断出错

所以需要改进状态
那么对于6来说,不能加入的条件是出现过两个2,或两个3,或1个2或1个3
那么不妨记录状态时一对儿一对儿记,这样可以解决上面的尴尬问题
发现总状态数很多,但是有用状态很少,可以记录在 map 里进行离散

可以记忆化搜索,但是感觉不好理解,所以采用递推的写法,每次更新一层,把每层有用的状态放进 vector 里更新即可

代码实现
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
const int maxn=1005;
const int maxm=5e6+5;
int cnt,tot,id[maxn][maxn],cnt1,SS[maxm];
long long n,nn,f[maxm],g[maxm],ans,a[maxm],num[maxm];
vector<pair<int,int> >p,q;
vector<int>to[maxm];
map<pair<int,int>,int>mp;
signed main(){
	cin>>n;
	nn=n;
	for(int i=2;1ll*i*i<=n;i++){
		if((n%i)==0){
			num[++cnt]=i;
			while((n%i)==0){
				n/=i;
			}
		}
	}
	if(n>1)num[++cnt]=n;
	n=nn;
	for(ll i=1;1ll*i*i<=n;i++){
		if((n%i)==0){
//			cout<<"ppp"<<endl;
			if(i!=1)a[++cnt1]=i;
			if(1ll*i*i!=n)a[++cnt1]=n/i;
		}
	}
//	cout<<cnt1<<" "<<cnt<<endl;
//	cout<<"hhh"<<endl;
	for(int i=1;i<=cnt1;i++){
		for(int j=1;j<=cnt;j++){
			if((a[i]%num[j])==0)to[i].push_back(j-1),SS[i]|=(1<<(j-1));
		}
	}
	for(int i=0;i<=cnt-1;i++){
		for(int j=0;j<=cnt-1;j++){
			if(id[j][i])id[i][j]=id[j][i];
			else id[i][j]=++tot;
		}
	}
	q.push_back(make_pair(0,0));
	f[0]=1;
	int cnt2=0;
	for(int i=1;i<=cnt*2+1;i++){
		tot=-1;
		for(int j=0;j<q.size();j++){
			cnt2++;
			int S=q[j].first;
			int T=q[j].second;
			ans=(ans+f[j])%mod;
			for(int k=1;k<=cnt1;k++){
				bool flag=false;
				for(int xx=0;xx<=to[k].size()-1;xx++){
					for(int yy=xx;yy<=to[k].size()-1;yy++){
						if(T&(1<<id[to[k][xx]][to[k][yy]])){
							flag=true;
							break;
						}
					}
					if(flag)break;
				}
				if(flag)continue;
				int NT=T;
				for(int xx=0;xx<=to[k].size()-1;xx++){
					for(int yy=0;yy<=cnt-1;yy++){
						if((S&(1<<yy))){
							NT|=(1<<id[to[k][xx]][yy]);
						}
					}
				}
				pair<int,int>pp=make_pair(S|SS[k],NT);
				if(mp.find(pp)==mp.end())mp[pp]=++tot,p.push_back(pp),g[tot]=f[j];
				else{
					g[mp[pp]]=g[mp[pp]]+f[j];
					if(g[mp[pp]]>mod)g[mp[pp]]-=mod;
				} 
			}
		}
		swap(f,g);
		memset(g,0,sizeof g);
		swap(p,q);
		p.clear();
		mp.clear();
	}
	cout<<ans-1<<endl;
//	cout<<cnt2<<endl;
	return 0;
}

C. Walker

为什么又是解方程题……

把式子展开,发现有 \(scale*sin\),\(scale*cos\),\(dx\),\(dy\) 四个未知数,选取两个点即可解出来
如果 \(n^2\) 枚举可以保证正确性
但是每次随机两个值,多次循环后不对的概率会降到极低

解出 \(sin\),\(cos\) 的值后可以使用 \(acos\) 这个函数解出弧度值,注意正负性不确定需要用 \(sin\) 进行验证

\(\color{white}{\mathbb{又恐琼楼玉宇,高处不胜寒}}\)

标签:pp,noip,int,32,long,因子,mp,maxm,模拟
来源: https://www.cnblogs.com/yang-cx/p/15112761.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有