P9076 [PA2018] PIN 题解

· · 题解

传送门
数学好题。
首先,题目要求 ba 的倍数,cb 的倍数,a+b+c=n,所以 a 一定是 n 的因数。
接下来我们推一下 a,b,c 的值域。

$b$ 最小的时候只能是 $2a$,最大的时候需要考虑到 $c$。最大时柿子为 $a+b+2b=n$,这里容易发现 $b=\frac{n-a}{3}$,所以 $b\in[2a,\lfloor\frac{n-a}{3}\rfloor]$。 $c$ 最小的时候是 $2b$,最大时柿子为 $a+2a+c=n$,容易得出 $c=n-3a$,所以 $c\in[2b,n-3a]$。 所以,我们可以先把 $a$ 的因数找出来,之后枚举一下,超过 $\lfloor\frac{n}{7}\rfloor$ 就不枚举。 设这个因数为 $x$,那么 $a=x$,$b+c=n-x=ya+zya$。 $a+b+c=a+ya+zya=a\times(1+y+zy)$,设 $d=\frac{n}{a}-1$,这里的 $d=y+zy$。 我们需要求出满足条件的 $y,z$ 有多少组。 我们枚举 $y$,从 $2$ 开始,不能出现 $ay\le \lfloor\frac{n-a}{3}\rfloor$ 的情况。 容易发现,在 $(a-y)\bmod y=0$ 的情况下可以构造出一组解。这个柿子等同于 $a\bmod y=0$。 所以,这个问题转化成了求解 $a$ 的因数数量。 $y$ 只需要枚举到 $\sqrt{a}$ 就可以。 对于一个满足条件的 $y$,如何判断 $\frac{n}{y}$ 也满足情况呢? 首先,需要有 $\frac{n}{y}≠y$。 这里需要判断能否构造出 $c$,如果 $(a-\frac{a}{y})\bmod \frac{a}{y}≠0$,那么无法构造出 $c$,$y$ 就不对。 还需要判断 $a-\frac{a}{y}=\frac{a}{y}$。如果等于,说明 $b=c$,是错误的。 CODE: ```cpp //Code by __dest__ruct__or__(uid=592238) #include <iostream> #include <vector> using namespace std; #define umap unordered_map #define uset unordered_set #define ll long long #define ld long double #define pii pair<int,int> #define pll pair<long long,long long> const ll INF=9223372036854775807; namespace mySTL{ inline int max(int a,int b){return a>b?a:b;} inline int min(int a,int b){return a<b?a:b;} inline ll max(ll a,ll b){return a>b?a:b;} inline ll min(ll a,ll b){return a<b?a:b;} inline ld min(ld a,ld b){return a<b?a:b;} inline ld max(ld a,ld b){return a>b?a:b;} inline int _abs(int a){return a<0?-a:a;} inline int read(){char c=getchar();int f=1,ans=0; while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9')ans*=10,ans+=c-'0',c=getchar(); return ans*f;} inline long long readll(){char c=getchar();long long f=1,ans=0; while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9')ans*=10,ans+=c-'0',c=getchar(); return ans*f;} inline void swap(int &a,int &b){a^=b,b^=a,a^=b;} inline void swap(ll &a,ll &b){a^=b,b^=a,a^=b;} inline void write(int x){if(x<0){putchar('-');x=-x;} if(x>=10){write(x/10);}putchar(x%10+'0');} inline void writell(long long x){if(x<0){putchar('-');x=-x;} if(x>=10){writell(x/10);}putchar(x%10+'0');} inline ll pw(ll a,ll b,ll p){if(b==0)return 1; if(b==1)return a%p; ll mid=pw(a,b/2,p)%p; if(b&1)return mid*mid%p*a%p;else{return mid*mid%p;}} inline int gcd(int a,int b){return b?gcd(b,a%b):a;} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline int lcm(int a,int b){return a*b/gcd(a,b);} } using namespace mySTL; int n,ans,sz,a; vector<int>v; int main(void){ n=read(); for(int i=1;i<=n/i;i++){//求因数 if(n%i!=0){ continue; } v.push_back(i); if(i!=n/i){ v.push_back(n/i); } } sz=v.size(); for(int i=0;i<sz;i++){//枚举因数(构造a) if(v[i]>n/7){ continue; } a=n/v[i]-1; for(int j=2;j*v[i]<=(n-v[i])/3&&j<=a/j;j++){//构造y if(a%j==0){ ans++; if(a/j!=j&&(a-a/j)%(a/j)==0&&(a-a/j)!=(a/j)){//判断a除以y能否使用 ans++; } } } } write(ans); return 0; } ```