简要题意:
求 1 ≤ x ≤ n , 1 ≤ y ≤ m 1\leq x\leq n,1\leq y\leq m 1≤x≤n,1≤y≤m 的 x y x^y xy 有多少种不同的结果。
n , m ≤ 5 e 18 n,m\leq 5e18 n,m≤5e18
题解:
原题TCO2013 2A 1000,数据范围只有 1e9。
其实这个数据范围 5 e 18 5e18 5e18 没有什么意思,不过是一些诡异的搜索优化,没有通用性和参考价值,不过这里还是说一下。
考虑除了 1 1 1 的剩下 n − 1 n-1 n−1 个数,全部 m m m 次方之后扣掉重复的。
记 s z [ i ] sz[i] sz[i] 为开 i i i 次方之后不能再开任意 i > 1 i > 1 i>1 次方的数的数量,这个随便算算即可,也是容斥。
然后考虑 s z [ i ] ( i > 1 ) sz[i](i > 1) sz[i](i>1) 集合中的数,我们考虑扣掉它的贡献和 i i i 更小的集合的贡献的重复部分,就是说计算 i × [ 1 , m ] i \times [1,m] i×[1,m] 和 [ 1 , i ) × [ 1 , m ] [1, i)\times [1,m] [1,i)×[1,m] 中有多少个重复的。
枚举 j < i j < i j<i 考虑计算 i × [ 1 , m ] i\times[1,m] i×[1,m] 和 j × [ 1 , m ] j \times [1,m] j×[1,m] ,且没有在 j < k < i j < k < i j<k<i 的 k × [ 1 , m ] k \times [1,m] k×[1,m] 中出现的数个数。
考虑在 j × [ 1 , m ] j\times [1,m] j×[1,m] 的集合里面进行容斥。
首先注意到在 [ 1 , m ] [1,m] [1,m] 里面选的数乘上 j j j 之后必须是 i i i 的倍数,也就是只考虑 i / g c d ( i , j ) i/gcd(i,j) i/gcd(i,j) 的倍数。
如果这个数再要在 k ∗ [ 1 , m ] k * [1,m] k∗[1,m] 这个 集合里面出现,又需要一个 l c m lcm lcm,就是 l c m ( i , j , k ) / j lcm(i,j,k)/j lcm(i,j,k)/j 的倍数。
这样算下来数很大,容斥的时候很快达到上界,可以跑 5 e 18 5e18 5e18。
然后就是原题的优化,拎出来把整除的丢掉。容斥也不要用 dfs ,直接归并,因为质因子数有限,状态数不会太多。
最后一个优化是考虑 i / g c d ( i , j ) i/gcd(i,j) i/gcd(i,j) 和容斥用的数的集合,这个也有一部分重复,用个 m a p < p a i r , i n t > map<pair,int> map<pair,int> 存一下一起算 。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
using pli=std::pair<ll,int>;
#define fi first
#define se second
cs int mod=1004535809;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int MD(ll x){return x>=mod?x%mod:(x<0?x%mod+mod:x);}
bool cmp(ll y,int k,ll x){
for(int re i=1;i<=k;++i){
x/=y;if(!x)return false;
}return true;
}
ll sqrt(ll x,int k){
ll y=std::pow(x,1./k);
while(!cmp(y,k,x))--y;
while(cmp(y,k,x))++y;--y;
return y;
}
void merge(std::vector<pli> &a,std::vector<pli> &b,std::vector<pli> &res){
size_t ah=0,bh=0;res.clear();
while(ah<a.size()&&bh<b.size()){
if(a[ah].fi<b[bh].fi)
res.push_back(a[ah++]);
else if(a[ah].fi>b[bh].fi)
res.push_back(b[bh++]);
else {
if(add(a[ah].se,b[bh].se))
res.push_back(pli(a[ah].fi,
add(a[ah].se,b[bh].se)));
++ah,++bh;
}
}while(ah<a.size())res.push_back(a[ah++]);
while(bh<b.size())res.push_back(b[bh++]);
}
void merge_all(std::vector<pli> *h,int n,std::vector<pli> &res){
std::vector<pli> vec;auto tmp=&vec;
std::priority_queue<std::pair<int,std::vector<pli>*> >q;
for(int re i=0;i<n;++i)if(h[i].size())
q.push({-(int)h[i].size(),&h[i]});
if(q.empty()){res.clear();return;}
if(q.size()==1){res=*q.top().se;return;}
while(q.size()>1){
auto t1=q.top().se;q.pop();
auto t2=q.top().se;q.pop();
if(q.empty())tmp=&res;
merge(*t1,*t2,*tmp);
q.push({-(int)tmp->size(),tmp});
tmp=t1;
}
}
ll n,m;
int sz[70],coef[70][70];
int id[70][70],dn[70];
std::vector<pli> h,hs[70];
void Main(){
scanf("%lld%lld",&n,&m);int mx=0;
while((n>>mx)>1)++mx;
for(int re i=mx;i;--i){
sz[i]=MD(sqrt(n,i)-1);
for(int re j=i+i;j<=mx;j+=i)
Dec(sz[i],sz[j]);
}for(int re i=1;i<=mx;++i)
for(int re j=0;j<i;++j)
coef[i][j]=i/std::__gcd(i,j);
int ans=add(1,mul(MD(n-1),MD(m)));
std::map<pli,int> mp;
for(int re j=2;j<=mx;++j)
for(int re k=1;k<j;++k){
int div=j/std::__gcd(j,k);
std::vector<int> d;ll st=0;
for(int re l=k+1;l<j;++l)
d.push_back(l/std::__gcd(div*k,l));
std::sort(d.begin(),d.end());int ct=0;
for(size_t re i=0;i<d.size();++i){
bool fl=false;
for(size_t re l=0;l<i&&!fl;++l)
fl=d[i]%d[l]==0;
if(!fl)st|=1ll<<d[i],++ct;
}Inc(mp[pli(st,div)],sz[j]);
}
for(int re i=1;i<=mx;++i)
for(int re j=1;j<=i;++j)
if(i%j==0)id[i][j]=dn[i]++;
for(cs auto &t:mp){
h.clear();h.push_back(pli(1,1));
ll lim=m/t.fi.se;
for(int re i=1;i<=mx;++i)
if((t.fi.fi>>i)&1){
for(int re j=0;j<dn[i];++j)
hs[j].clear();
for(auto &p:h){
int r=coef[i][p.fi%i];
if(r>1){
hs[0].push_back(p);
if(p.fi<=lim/r)
hs[id[i][r]].push_back({p.fi*r,dec(0,p.se)});
}
}merge_all(hs,dn[i],h);
}
int vl=0;
for(auto &p:h)
Inc(vl,mul(p.se,MD(lim/p.fi)));
Dec(ans,mul(t.se,vl));
}
cout<<ans<<"\n";
}
inline void file(){
#ifdef zxyoi
freopen("pow.in","r",stdin);
#else
freopen("pow.in","r",stdin);
freopen("pow.out","w",stdout);
#endif
}signed main(){file();Main();return 0;}