洛谷 P6511 [QkOI#R1] Quark and Equations 数学

洛谷 P6511 [QkOI#R1] Quark and Equations 数学_第1张图片

首先要进行一些特判:

  1. m = 1 m=1 m=1 n = 1 n=1 n=1 m > n m>n m>n 时,结果为 0 0 0

  2. m = n m=n m=n m = n − 1 m=n-1 m=n1 时,结果为 1 1 1

此时 2 ≤ m ≤ n − 2 2\le m\le n-2 2mn2,对 i < j ii<j i ≥ j i\ge j ij 这两种情况分别进行讨论:

  1. i < j ii<j 时,原式子变成

⌈ j i ⌉ = m \lceil\frac{j}{i}\rceil=m ij=m

由于 ⌈ j i ⌉ = ⌊ j − 1 i ⌋ + 1 \lceil\dfrac{j}{i}\rceil=\lfloor\dfrac{j-1}{i}\rfloor+1 ij=ij1+1,因此上式等价于:

⌊ j − 1 i ⌋ + 1 = m \begin{aligned} \lfloor\dfrac{j-1}{i}\rfloor+1&=m\\ \end{aligned} ij1+1=m

再代入 i + j = n i+j=n i+j=n 得:

⌊ n − i − 1 i ⌋ + 1 = m ⌊ n − 1 i ⌋ = m ( 1 ) \begin{aligned} \lfloor\dfrac{n-i-1}{i}\rfloor+1&=m\\ \lfloor\dfrac{n-1}{i}\rfloor&=m\qquad (1)\\ \end{aligned} ini1+1in1=m=m(1)

因此转化为 i < j ii<j 时,有多少个 i i i 满足式 ( 1 ) (1) (1)

  1. i ≥ j i\ge j ij 时,原式子变成

⌊ i j ⌋ = m − 1 ⌊ n − j j ⌋ = m − 1 ⌊ n j ⌋ = m ( 2 ) \begin{aligned} \lfloor\frac{i}{j}\rfloor&=m-1\\ \lfloor\frac{n-j}{j}\rfloor&=m-1\\ \lfloor\frac{n}{j}\rfloor&=m\qquad(2)\\ \end{aligned} jijnjjn=m1=m1=m(2)

因此转化为 i > j i>j i>j 时,有多少个 j j j 满足式 ( 2 ) (2) (2)

然后可以推出各自的范围:

i < j ii<j 时:
⌊ n − 1 i ⌋ = m m ≤ n − 1 i i ≤ n − 1 m i ≤ ⌊ n − 1 m ⌋  因为  i  是整数 m > n − 1 i − 1 m + 1 > n − 1 i i > n − 1 m + 1 i ≥ ⌊ n − 1 m + 1 ⌋ + 1 \begin{aligned} \lfloor\frac{n-1}{i}\rfloor&=m\\ m&\le\frac{n-1}{i}\\ i&\le\frac{n-1}{m}\\ i&\le\lfloor\frac{n-1}{m}\rfloor\text{ 因为 $i$ 是整数}\\ m&>\frac{n-1}{i}-1\\ m+1&>\frac{n-1}{i}\\ i&>\frac{n-1}{m+1}\\ i&\ge\lfloor\frac{n-1}{m+1}\rfloor+1\\ \end{aligned} in1miimm+1ii=min1mn1mn1 因为 i 是整数>in11>in1>m+1n1m+1n1+1

i ≥ j i\ge j ij 时:

⌊ n j ⌋ = m m ≤ n j j ≤ n m j ≤ ⌊ n m ⌋ m > n j − 1 m + 1 > n j j > n m + 1 j ≥ ⌊ n m + 1 ⌋ + 1 \begin{aligned} \lfloor\frac{n}{j}\rfloor&=m\\ m&\le\frac{n}{j}\\ j&\le\frac{n}{m}\\ j&\le\lfloor\frac{n}{m}\rfloor\\ m&>\frac{n}{j}-1\\ m+1&>\frac{n}{j}\\ j&>\frac{n}{m+1}\\ j&\ge\lfloor\frac{n}{m+1}\rfloor+1\\ \end{aligned} jnmjjmm+1jj=mjnmnmn>jn1>jn>m+1nm+1n+1

因此得到两个不等式组:

{ i ≤ ⌊ n − 1 m ⌋ i ≥ ⌊ n − 1 m + 1 ⌋ + 1 { j ≤ ⌊ n m ⌋ j ≥ ⌊ n m + 1 ⌋ + 1 \begin{aligned} &\begin{cases} i&\le\lfloor\dfrac{n-1}{m}\rfloor\\ i&\ge\lfloor\dfrac{n-1}{m+1}\rfloor+1\\ \end{cases}\\ &\begin{cases} j&\le\lfloor\dfrac{n}{m}\rfloor\\ j&\ge\lfloor\dfrac{n}{m+1}\rfloor+1\\ \end{cases} \end{aligned} iimn1m+1n1+1jjmnm+1n+1

因此最终的答案就是

⌊ n − 1 m ⌋ − ⌊ n − 1 m + 1 ⌋ + ⌊ n m ⌋ − ⌊ n m + 1 ⌋ \lfloor\dfrac{n-1}{m}\rfloor-\lfloor\dfrac{n-1}{m+1}\rfloor+\lfloor\dfrac{n}{m}\rfloor-\lfloor\dfrac{n}{m+1}\rfloor mn1m+1n1+mnm+1n

代码如下:

#include
#include
using namespace std;
typedef long long ll;
int T;
ll n,m;
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        ll res=0;
        if(m==1||m>n||n==1)res=0;
        else if(m==n||m==n-1)res=1;
        else res=(n-1)/m-(n-1)/(m+1)+n/m-n/(m+1);
        printf("%lld\n",res);
    }
    return 0;
}

当时我是用分块做的:

#include
#include
using namespace std;
typedef long long ll;
int T;
ll n,m;
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&n,&m);
        ll res=0;
        if(m==1||m>n||n==1)res=0;
        else if(m==n||m==n-1)res=1;
        else{
            //if(m==2&&(n%2==0))res++;
            ll k;
            ll i=(n-1)/(m+1);
            for(;i<=(n-1)/2;i=k+1){
                k=(n-1)/((n-1)/i);
                if((n-1)/i==m){
                    res+=k-i+1;
                    break;
                }
            }
            ll j=n/(m+1);
            for(;j<=(n-1)/2;j=k+1){
                k=n/(n/j);
                if(n/j==m){
                    res+=k-j+1;
                    break;
                }
            }
        }
        printf("%lld\n",res);
    }
    return 0;
}

你可能感兴趣的:(数论/数学)