求 区间[a,b]内满足p^k*q*^m(k>m)的数的个数

本文介绍了一种算法,用于计算在特定区间[a, b]内能够表示为x * p^k * q^m (k > m)形式的整数个数,其中p和q为素数。通过枚举m值并应用容斥原理来实现,避免了数值溢出的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

1<=a,b<=10^18,p,q都是素数  2<=p,q<=10^9;

求在[a,b]内可以表示为  x*p^k*q^m  k > m   的数的个数


分析:

由于要小于b,因此m一定小于 log10(b)/log10(p*q);

因此我们可以枚举m,中间计数的时候需要用到容斥。


具体看代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

LL mypow(LL a,int b)
{
    LL ans = 1;
    while(b){
        if(b&1){
            ans=ans*a;
            b--;
        }
        b>>=1;
        a=a*a;
    }
    return ans;
}

int main()
{
    LL a,b,p,q;
    while(~scanf("%lld%lld%lld%lld",&a,&b,&p,&q)){
        int mmax = log10(b*1.0)/log10(p*q*1.0)+1;
        LL ans = 0;
        for(int i=0;i<=mmax;i++){
            if(mypow(p,i+1)>b*1.0/mypow(q,i))//防止爆long long
                break;
            for(int j=i+1;j<64;j++){
                if(mypow(p,j)>b*1.0/mypow(q,i)) break;//防止爆long long
                LL tmp=mypow(p,j)*mypow(q,i);
                LL cnt1 = b/tmp,cnt2=(a-1)/tmp;//由于是闭区间 因此要用a-1;
                ans += cnt1;
                ans -= cnt2;
                ans -= cnt1/p;
                ans -= cnt1/q;
                ans += cnt1/p/q;
                ans += cnt2/p;
                ans += cnt2/q;
                ans -=cnt2/p/q;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}


# P4462 [CQOI2018] 异或序列 ## 题目描述 已知一个长度为 $n$ 的整数列 $a_1,a_2,\dots,a_n$,给定查询参 $l,r$,问在 $a_l,a_{l+1},\dots,a_r$ 区间内,有多少区间满足异或等于 $k$。也就是说,对于所有的 $x,y (l \leq x \leq y \leq r)$,能够满足 $a_x \oplus a_{x+1} \oplus \dots \oplus a_y = k$ 的 $x,y$ 有多少组。 ## 输入格式 输入文件第一行,为 $3$ 个整数 $n,m,k$。 第二行为空格分开的 $n$ 个整数,即 $a_1,a_2,..a_n$。 接下来 $m$ 行,每行两个整数 $l_j,r_j$,表示一次查询。 ## 输出格式 输出文件共 $m$ 行,对应每个查询的计算结果。 ## 输入输出样例 #1 ### 输入 #1 ``` 4 5 1 1 2 3 1 1 4 1 3 2 3 2 4 4 4 ``` ### 输出 #1 ``` 4 2 1 2 1 ``` ## 说明/提示 对于 $30\%$ 的据,$1 \leq n, m \leq 1000$。 对于 $100\%$ 的据,$1 \leq n, m \leq 10^5$,$0 \leq k, a_i \leq 10^5$,$1 \leq l_j \leq r_j \leq n$。 #include <bits/stdc++.h> #define ll long long using namespace std; const ll N=2e5; struct node{ ll l,r,f,ans; }b[N+5]; ll n,m,k; ll blk[N+5],lenb; ll a[N+5],pre[N+5]; ll cnt[N+5]; ll lp,rp,s; bool cmp(node l1,node l2){ if(blk[l1.l]==blk[l2.l]) return l1.r<l2.r; return blk[l1.l]<blk[l2.l]; } bool cmpf(node l1,node l2){ return l1.f<l2.f; } void solve(ll l,ll r,ll &ans){ while(lp<l){ s-=cnt[k^pre[lp-1]]; cnt[pre[lp]]--; lp++; } while(lp>l){ lp--; cnt[pre[lp]]++; s+=cnt[k^pre[lp-1]]; } while(rp<r){ rp++; s+=cnt[k^pre[rp]]; cnt[pre[rp]]++; if((pre[lp-1]^pre[rp])==k) s++; } while(rp>r){ s-=cnt[k^pre[rp]]; cnt[pre[rp]]--; if((pre[lp-1]^pre[rp])==k) s--; rp--; } ans=s; return; } int main(){ scanf("%lld%lld%lld",&n,&m,&k); ll sx=1; lenb=(ll)sqrt(n); for(ll i=1;i<=n;i++){ blk[i]=sx; if(sx%lenb==0) sx++; } for(ll i=1;i<=n;i++){ scanf("%lld",&a[i]); pre[i]=(pre[i-1]^a[i]); } for(ll i=1;i<=m;i++){ scanf("%lld%lld",&b[i].l,&b[i].r); } sort(b+1,b+m+1,cmp); lp=rp=cnt[pre[1]]=1; if(k==0) s=1; for(ll i=1;i<=m;i++){ solve(b[i].l,b[i].r,b[i].ans); } sort(b+1,b+m+1,cmpf); for(ll i=1;i<=m;i++) printf("%lld\n",b[i].ans); return 0; } 不改变原来代码写法情况下标出并修正错误
07-31
# T617559 「TPOI-5A」Luminescence ## 题目背景 ![](https://cdn.luogu.com.cn/upload/image_hosting/ownsj515.png) (图片来自 Phigros 曲绘,侵删。) ## 题目描述 给定 $n$ 与两个长度为 $n$ 的序列 $a,b$。定义一个 $0\sim n-1$ 的排列 $q$ 是 **魔怔的**,当且仅当: - $\forall 1\le k\le n,\min^k_{i=1}q_i=a_k$。 - $\forall 1\le k\le n,\min^n_{i=k}q_i=b_k$。 定义一个排列 $q$ 的权值为 $\sum_{1\le l\le r\le n}\operatorname{mex}_{l\le i\le r}q_i$,所有魔怔的排列的权值之。答案对 $998244353$ 取模。 一个集合 $M$ 的 $\operatorname{mex}(M)$ 定义为最小的没有在 $M$ 中出现的自然。如 $\text{mex}\{1,2,3,4\}=0,\text{mex}\{0,1,3,4\}=2$。 ## 输入格式 本题有多组测试据。对于每个测试点,先输入一个正整数 $T$,表示据组。 对于每一组测试据,第一行一个正整数 $n$, 第二行输入 $n$ 个整数 $a_1,a_2,\dots,a_n$,第三行 $n$ 个整数 $b_1,b_2,\dots,b_n$。 ## 输出格式 对于每一组测试据,输出一行一个整数,表示所有魔怔的排列的权值之。 ## 输入输出样例 #1 ### 输入 #1 ``` 3 4 0 0 0 0 0 1 2 3 4 1 0 0 0 0 0 2 2 4 0 0 0 0 0 1 1 1 ``` ### 输出 #1 ``` 10 11 14 ``` ## 说明/提示 |$\text{Subtask}$|$n\le$|$\sum n\le$|分值| |:-:|:-:|:-:|:-:| |$1$|$8$|$800$|$20$| |$2$|$10^3$|$10^4$|$40$| |$3$|$2\times10^5$|$2\times10^6$|$40$| 对于 $100\%$ 的据,$1 \le n \le 2 \times 10^5,0 \le a_i,b_i < n, \sum n \le 2 \times 10^6$。 **对于每组据保证存在至少一个魔怔的排列。** c++,不用vector,注释
08-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值