卧薪尝胆,厚积薄发。
function
Date: Mon Mar 04 15:57:26 CST 2019 In Category: NoCategory

Description:

给一个函数: $$ f(x)=\prod_{i=0}^k(x-i^2) $$ $k$ 为满足 $x-k^2>0$ 的最大自然数。
给出 $L,R,P$ ,求有多少个正整数 $x\in[L,R]$ 满足 $P|f(x)$ 。
$1\leqslant L,R\leqslant 10^{18},1\leqslant P\leqslant 10^6$

Solution:

设: $$ f_k(x)\prod_{i=0}^k(x-i^2) $$ 首先由于 $f$ 是一个多项式,因此有: $f(x+P)=f(x)\bmod P$ 。那么我么就可以对于每个 $i\in[0,P)$ 统计一下 $\bmod P=i$ 的 $x$ 中合法的个数,这个可以这样做,我们可以求出一个 $maxk[i]$ 表示 $\bmod P=i$ 的 $x$ 中 $f(x)\bmod P=0$ 的最小的 $k$ ,因为由于 $f(x)$ 单调而且是一个多项式,所以如果 $f_k(x)$ 合法,那么 $k+1$ 也一定是合法的,也就是说 $x>k^2,x\bmod P=i$ 的 $x$ 都合法,因此我们如果可以计算出 $maxk[i]$ 就可以计算 $x\bmod P=i,P|f(x)$ 的 $x$ 个数了,我们可以再设一个 $dp[i][j]$ 表示模 $P$ 为 $i$ 并且 $f(x)$ 是质数 $j$ 在 $P$ 中的幂 $j^q$ 的倍数的 $k$ 最小是几,那么有 $maxk[i]=\max_j(dp[i][j])$ ,那么我们就可以不停找直到找够了 $q$ 个为止,也就是说从小往大枚举 $x-k^2=0\bmod j$ 的 $k$ ,每次消掉 $x-k^2$ 中 $j$ 的幂,会发现这个是一个二次剩余,但是我们可以把它提前预处理出来放进一个 $vector$ 里。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cctype>
#include<cstring>
using namespace std;
typedef long long ll;
ll L,R,P;
#define MAXN 1000010
ll ans[MAXN];
vector<ll> g[MAXN];
#define INF 0x3f3f3f3f3f3f3f3f
ll calc(ll n)
{
if(n == 0)return 0;
ll res = 0;
for(int i = 0;i < P;++i)
{
if(ans[i] != INF)
{
if(ans[i] > n)continue;
if(n >= i)res += (n - i) / P + 1;
if(ans[i] >= i)res -= (ans[i] - i) / P + 1;
}
//cout << ans[i] << " ";
}//cout << endl;
return res;
}
void solve(ll p,ll k)
{
for(ll i = 0;i < P;++i)g[i].clear();
for(ll i = 0;i < P;++i)g[i * i % p].push_back(i);
for(ll i = 0;i < P;++i)
{
vector<ll> v = g[i % p];
int cnt = k;
ll x = 0;
while(cnt > 0)
{
for(vector<ll>::iterator it = v.begin();it != v.end();++it)
{
ll val = (i - *it * *it % P + P) % P;//cout << val << endl;
while(cnt && val % p == 0)val /= p,--cnt;
if(cnt == 0){ans[i] = max(ans[i],(*it + x) * (*it + x));break;}
}
if(cnt == k){ans[i] = INF;break;}
x += P;
}
}
return;
}
int main()
{
scanf("%lld%lld%lld",&L,&R,&P);
ll pr = P;
for(int i = 2;i * i <= P;++i)
{
if(P % i == 0)
{
int cnt = 0;
while(pr % i == 0)++cnt,pr /= i;
solve(i,cnt);
}
}
if(pr != 1)solve(pr,1);
cout << (calc(R) - calc(L - 1)) << endl;
return 0;
}
In tag: DP-DP
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡