『数学』做题记录

P8380

出在模拟赛里面了,推的式子不能浪费,所以提供两种解法。

玩一下什么情况 \(y^x=x^z\) 就是考虑将 \(x\) 表示为 \(m^a\) 的形式,\(y\) 表示为 \(m^b\) 的形式,然后需要满足的是 \(m^{bx}=m^{az}\),而由于我们是在计数,考虑构造一种双射的形式:对于一个三元组 \((m,a,b)\) 能唯一对应一个 \((x,y)\),对于一组合法的 \((x,y)\) 一定能射到一组 \((m,a,b)\) 上。

不妨通过应定 \(\gcd(a,b)=1\) 来保证这一点,考虑一组 \((x,y)\) 能表示成 \((m,a,b)\)\(\gcd(a,b)\not=1\),不难通过变化为 \((m^{\gcd(a,b)},\dfrac{a}{\gcd(a,b)},\dfrac{a}{\gcd(a,b)})\) 来保证计数不重。

那么可以很轻松地写出式子:

\[\sum\limits_{x=1}^{A} \sum\limits_{y=1}^{B} \sum\limits_{z=1}^{C} [y^x=x^z] \]

特判一下 \(m=1\) 的情况:

\[=C+\sum\limits_{m> 1}^{} \sum\limits_{a=1}^{\log _{m}A} \sum\limits_{b=1}^{\log _{m}B} [\gcd(a,b)=1][\dfrac{bm^a}{a}\leq C][a|bm^a] \]

由于 \(\gcd(a,b)=1\)

\[=C+\sum\limits_{m> 1}^{} \sum\limits_{a=1}^{\log _{m}A} \sum\limits_{b=1}^{\log _{m}B} [\gcd(a,b)=1][\dfrac{bm^a}{a}\leq C][a|m^a] \]

\[=C+ \sum\limits_{a=1}^{\log _{2}A} \sum\limits_{b=1}^{\log _{2}B} \sum\limits_{m> 1}[\gcd(a,b)=1][\dfrac{bm^a}{a}\leq C][a|m^a][m^a \leq A][m^b \leq B] \]

\[=C+ \sum\limits_{a=1}^{\log _{2}A} \sum\limits_{b=1}^{\log _{2}B} \sum\limits_{m> 1}[\gcd(a,b)=1][\dfrac{bm^a}{a}\leq C][a|m^a][m^a \leq A][m^b \leq B] \]

实际上,推到这步这题就结束了,但是这题是个大粪卡常题。

你但凡观察一下,你直接枚举 \(a,b\) 然后算出 \(m\) 的上界 \(t\),然后算个 \(\sum\limits_{m=2}^{t} [a|m^a]\) 就没了。

然后想了一下,你可能想在 \(t\) 比较小的时候预处理这部分。

而不难发现,当 \(a\geq 3\),有 \(t\leq 10^6\)

然后对于 \(a=1\) 这个 \(a|m^a\) 没有限制,而 \(a=2\)\(a|m^2\) 其实就是 \(2|m\)

好,这个做法通过 pow 调整可以做到 \(O(n\log n+T \log^2 n)\),或者通过二分做到 \(O(n\log n+T \log^2 n \log \log n)\)

有预处理的做法没意思,我们搞点有意思的,这部分大致是我赛时的思路(虽然赛时没有预处理而是后面这部分暴力做了)。

考虑一下你在写暴力判断 \(a|m^a\) 怎么判断的,初始一个 \(q=a\),不断将 \(q \rightarrow \dfrac{q}{\gcd(q,m)}\) 操作 \(a\) 次,若 \(q=1\) 则返回 true。

这个是在做什么?考虑 \(m\) 的所有质因子 \(p^e\),考虑 \(a\) 中含有的同样质因子 \(p^{e^{\prime}}\),上述判断相当于是对于所有 \(p\),判断是否都有 \(ea\geq e^{\prime}\),所以相当于我给每个 \(a\) 中质因子 \(p\) 的指数在 \(m\) 中都有限制。

那么不难算出这个偏序关系中最小的 \(m^{\prime}\),那么对于 \(m\)\(m^{\prime}\) 的倍数就是 \(a|m^a\) 成立的充要条件。

设这个 \(m^{\prime}=f(a)\),那么 \(\sum\limits_{m=2}^{t}[a|m^a]=[f(a)=1](t-1)+[f(a)>1] \lfloor\dfrac{t}{f(a)}\rfloor\)

这个做法的复杂度同样是 \(O(T \log^2 n \log \log n)\)

Code:

#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2")
//#pragma GCC optimize("Ofast","unroll-loops","inline")
#include<bits/stdc++.h>
#define ll long long
#define int ll
#define pb push_back
using namespace std;
const int N=1e6+20,M=1e6+20,mod=1e9+7,LGN=63;
const int mx[]={0,1000000000000000010ll,1000000010,1000010,32000,4000,1010};
const int Mx=2e18;
const int Lim=1e18;
namespace FastIO {
	struct IO {
	    char ibuf[(1 << 20) + 1], *iS, *iT, obuf[(1 << 20) + 1], *oS;
	    IO() : iS(ibuf), iT(ibuf), oS(obuf) {} ~IO() { fwrite(obuf, 1, oS - obuf, stdout); }
		#if ONLINE_JUDGE
		#define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
		#else
		#define gh() getchar()
		#endif
		inline bool eof (const char &ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == 't' || ch == EOF; }
	    inline long long read() {
	        char ch = gh();
	        long long x = 0;
	        bool t = 0;
	        while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
	        while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
	        return t ? ~(x - 1) : x;
	    }
	    inline void read (char *s) {
	    	char ch = gh(); int l = 0;
	    	while (eof(ch)) ch = gh();
	    	while (!eof(ch)) s[l++] = ch, ch = gh();
	    }
	    inline void read (double &x) {
	    	char ch = gh(); bool t = 0;
	    	while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
	    	while (ch >= '0' && ch <= '9') x = x * 10 + (ch ^ 48), ch = gh();
	    	if (ch != '.') return t && (x = -x), void(); ch = gh();
	    	for (double cf = 0.1; '0' <= ch && ch <= '9'; ch = gh(), cf *= 0.1) x += cf * (ch ^ 48);
	    	t && (x = -x);
	    }
	    inline void pc (char ch) {
	    	#ifdef ONLINE_JUDGE
	    	if (oS == obuf + (1 << 20) + 1) fwrite(obuf, 1, oS - obuf, stdout), oS = obuf; 
	    	*oS++ = ch;
	    	#else
	    	putchar(ch);
	    	#endif
		}
		template<typename _Tp>
	    inline void write (_Tp x) {
	    	static char stk[64], *tp = stk;
	    	if (x < 0) x = ~(x - 1), pc('-');
			do *tp++ = x % 10, x /= 10;
			while (x);
			while (tp != stk) pc((*--tp) | 48);
	    }
	    inline void write (char *s) {
	    	int n = strlen(s);
	    	for (int i = 0; i < n; i++) pc(s[i]);
	    }
	} io;
	inline long long read () { return io.read(); }
	template<typename Tp>
	inline void read (Tp &x) { io.read(x); }
	template<typename _Tp>
	inline void write (_Tp x) { io.write(x); }
}
using namespace FastIO;
int fl[LGN][LGN],f[LGN],pw[LGN][N],L[LGN];
int qpow(int a,int b){
	if(b==0) return 1;
	int res=1;
	while(b){if(b&1){if(res>Lim/a) return Lim+1;res=res*a;}b>>=1;if(!b) break;if(a>Lim/a) return Lim+1;a=a*a;}
	return res;
}
inline int get(int x,int v){
	if(v==1) return x;
	if(v==2) return sqrtl(x);
	int l=0,r=L[v],ans=0;
	while(l<=r){
		int mid=(l+r)/2;
		if(pw[v][mid]<=x) l=mid+1,ans=mid;
		else r=mid-1;
	}
	return ans;
}
inline int Lg(int x,int B){
	int res=0,p=1;
	while(p<=B/x) p*=x,res++;
	return res;
}
inline int calc(int i,int A,int B,int C){
	int p=Lg(2,B),res=0;
	int g=f[i];
	for(int y=1;y<=p;y++) if(fl[i][y]){
		int lim=get(B,y);
		lim=min(lim,get((ll)min((__int128)A,((__int128)C*i/y)),i));
		if(g==1){
			if(lim>1) res=(res+lim-1)%mod;
		}
		else res=(res+lim/g)%mod;
	}return res;
}
int A,B,C;
vector<int> e[LGN];
inline int gcd(int a,int b){if(!b||!a) return a+b;int az=__builtin_ctz(a),bz=__builtin_ctz(b),z=(az>bz)?bz:az,t;b>>=bz;while(a) a>>=az,t=a-b,az=__builtin_ctz(t),b=a<b?a:b,a=t<0?-t:t;return b<<z;}
inline bool chk(int x,int d){
	int p=x,tot=x;
	while(p!=1&&tot){
		int g=gcd(d,p);
		if(g==1) break;
		p/=g,tot--;
	}
	return p==1;
}
int g[LGN][N];
void solve(){
	A=read();B=read();C=read();
	int lim=Lg(2,A),L=Lg(2,B),res=0;
	for(int i=1;i<=lim;i++) res=(res+calc(i,A,B,C))%mod;
	write((C+res)%mod);io.pc('\n');
}
signed main(){
	for(int x=1;x<=62;x++){
		for(int y=1;y<=62;y++) if(gcd(x,y)==1) fl[x][y]=1,e[x].pb(y);
	}
	for(int x=3;x<=60;x++){
		L[x]=1;
		for(;qpow(L[x],x)<=Lim;L[x]++) ;
		for(int i=1;i<=L[x];i++) pw[x][i]=qpow(i,x);
	}
	for(int x=1;x<=62;x++){
		for(int y=1;y<=x;y++) if(x%y==0&&chk(x,y)){
			f[x]=y;break;
		}
	}
	int T=read();
	while(T--) solve();
	return 0;
}

没有精细实现,跑得很慢。

posted @ 2023-11-05 20:02  Detect-Perplexity  阅读(5)  评论(0编辑  收藏  举报