首页 > 其他分享 >Educational Codeforces Round 142 E. Divisors and Table

Educational Codeforces Round 142 E. Divisors and Table

时间:2023-02-07 20:22:21浏览次数:95  
标签:Educational 142 int 200100 Codeforces 因子 m1 cnt2 cnt1

链接:https://codeforces.com/problemset/problem/1792/E
题意:给定n * n乘法表,第a[ i ] [ j ] = i * j,给定m=m1 * m2,求m的所有因子中出现在表中的最小行的xor和。
n<=1e9,m1,m2<=1e9.
分析:对于m = 1e18,最多可表示为15个素数相乘,故最多有2^15-1个因子,数量级在4e4左右。求最小行,即为求最大列,即为求某个数可以分解r*c且c<=n,c尽量大。
考虑暴力做法,枚举每个因子的所有因子,找到最大的列,显然复杂度过大。再观察发现子问题包含最优解,一个数x的最大的c要不然是x,要不然是x的因子,那么对于其所有x/p的因子包含最优解,故可考虑递推。
f[x] 表示x所能表示的最大列数c,则f[x]=max(x,f[x/p1],f[x/p2],,,).这样做复杂度为最坏为T * 2^15 * log(m)。
代码:

//参考了网上大佬的代码(忘了是谁的了,,)
#include<bits/stdc++.h>
#define int long long
using namespace std;
map<int,int> mp;
int b[200100],f[200100],p[200100],poww[200100];
void dcp(int x){
	for(int i=2;i*i<=x;i++){
		while(x%i==0){
			x/=i;
			mp[i]++;
		}
	}
	if(x>1) mp[x]++; 
}
void dfs(int cur,int val,int cnt1,int &cnt2){
	if(cur>cnt1){
		b[++cnt2]=val;
		return;
	}
	for(int i=0;i<=poww[cur];i++){
		dfs(cur+1,val,cnt1,cnt2);
		val*=p[cur];
	}
}
void solve(){
	int n;cin>>n;mp.clear();
	int m1,m2;cin>>m1>>m2;
	int ans=0,anss=0;
	dcp(m1);dcp(m2);
	int cnt1=0,cnt2=0;
	for(auto it:mp){
		cnt1++;
		p[cnt1]=it.first;
		poww[cnt1]=it.second;
	}
	dfs(1,1,cnt1,cnt2);
	sort(b+1,b+cnt2+1);
	for(int i=1;i<=cnt2;i++){
		if(b[i]<=n) f[i]=b[i];
		else f[i]=0;
		for(int j=1;j<=cnt1;j++){
			if(b[i]%p[j]==0){
				f[i]=max(f[i],f[lower_bound(b+1,b+cnt2+1,b[i]/p[j])-b]);
			}
		}
		int t=b[i]/f[i];
			if(f[i]!=0&&t<=n){
				ans++;
				anss^=t;
			}
	}
	cout<<ans<<" "<<anss<<endl;
}
signed main(){
	int T;cin>>T;
	while(T--) solve();
}

标签:Educational,142,int,200100,Codeforces,因子,m1,cnt2,cnt1
From: https://www.cnblogs.com/wjhqwq/p/17099695.html

相关文章