1. 程式人生 > 其它 >近期做題的總結?(不定期更新)

近期做題的總結?(不定期更新)

高考考完了,考上帶學了,好耶(

開始嘗試做一些題復建,這裡是持續更新的近期做題記錄

Educational Codeforces Round 106 (Rated for Div. 2)

D

題意:給定$ c,d,x $

求滿足$ c*lcm(a,b)-d*gcd(a,b)=x $的對數考慮令$ a=A*gcd(a,b),b=B*gcd(a,b) $(重點,把列舉的$ a,b $從$ (a,b)=t $轉化成$ (A,B)=1 $的$A$和$B$)

稍微整理一下就會發現

原式的形式是$c*A*B*gcd(a,b)-d*gcd(a,b)=x$

$(c*A*B-d)*gcd(a,b)=x$

考慮列舉$x$的因數(即列舉$gcd(a,b)$),令其為$y$

則$y+d$需要是$c$的倍數

接下來考慮在已知$A*B$的情況下如何求解$A$和$B$對應的組數

發現因為$(A,B)=1$

考慮$A*B$的質因數,如果$A$選了一個質因數,$B$就不能選這個質因數。

也就是說答案是$\sum_{1<=i<=m}C_{m}^{i}$ 也就是$2^m$

現在問題是如何快速統計每個數字的因數個數

這裡可以用線性篩先對於每個數字求解一個$minp$,表示該數字的最小質因數。

則$d_x = d_{\frac{x}{minp}} + [\frac{x}{minp} == minp] $

然後就做完了。

Code:

#include <bits/stdc++.h>
using
namespace std; int T,c,d,x,Ans; const int N=30000005; bool IsPrime[30000007]; int Prime[30000007],Index,sp[30000007],val[30000007]; void Pre(){ for (int i=2;i<=N;i++){ if (!IsPrime[i]) Prime[++Index]=i,sp[i]=i; for (int j=1;j<=Index&&1ll*i*Prime[j]<=N;j++){ IsPrime[i*Prime[j]]=true
;sp[i*Prime[j]]=Prime[j]; if (i%Prime[j]==0) break; } } } int main(){ sp[1]=1; Pre(); for (int i=2;i<=N;i++){ if (sp[i/sp[i]]!=sp[i]) val[i]=val[i/sp[i]]+1; else val[i]=val[i/sp[i]]; } scanf("%d",&T); while (T--){ scanf("%d%d%d",&c,&d,&x); Ans=0; for (int i=1;i*i<=x;i++) if (x%i==0){ int res=x/i; int Now=i; res+=d;Now+=d; if (Now%c==0) {Ans+=(1<<val[Now/c]);} if (res%c==0 && 1ll*i*i!=x) {Ans+=(1<<val[res/c]);} } printf("%d\n",Ans); } return 0; }
蒟蒻のOIer 萌新の東方玩家 睿智の休伯利安清潔工 參上