CF976-F. Count Leaves-min25筛(红温了)
link:https://codeforces.com/contest/2020/problem/F
题意:给定
- 树的根是一个标有数字
的节点。这是树的第 层。 - 对于从
到 的每个 ,对于第 层的每个顶点,执行以下操作:如果当前顶点标记为 ,创建其子顶点并标记为 的所有可能的不同因此 。这些子顶点将位于 层。 层上的顶点就是树的叶子。
表示 的叶子结点个数,求 , .
(喜欢赛后过题)
观察
因此只要考虑
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0) using namespace std; typedef long long ll; constexpr int MOD=1e9+7; constexpr int N=3e6+5; int ksm(int a,int b){ int ret=1;a%=MOD; for(;b;b>>=1,a=(ll)a*a%MOD)if(b&1)ret=(ll)ret*a%MOD; return ret; } int inv(int x){return ksm(x,MOD-2);} int fact[N],inv_fact[N]; void init(){ fact[0]=1; rep(i,1,N-1)fact[i]=(ll)fact[i-1]*i%MOD; inv_fact[N-1]=inv(fact[N-1]); for(int i=N-1;i>=1;i--)inv_fact[i-1]=(ll)inv_fact[i]*i%MOD; } int C(int n,int k){ if(k>n)return 0; return (ll)fact[n]*inv_fact[k]%MOD*inv_fact[n-k]%MOD; } namespace Min25{ constexpr int maxs=2e5; void add(int &x,const int & y){x+=y;if(x>=MOD)x-=MOD;} void dec(int &x,const int & y){x+=MOD-y;if(x>=MOD)x-=MOD;} int sum(const int &x,const int & y){return x+y<MOD?x+y:(x+y-MOD);} int sub(const int &x,const int & y){return x<y?x+MOD-y:x-y;} template<typename T>long long sqrll(const T&x){return (ll)x*x;} long long global_n,lis[maxs + 1]; int K,d; int pri[maxs / 7], lpf[maxs + 1], spri[maxs + 1],pcnt,lim,cnt; int le[maxs + 1],ge[maxs + 1];//x<=sqrt(n),x>sqrt(n) int G[maxs + 1][2], Fprime[maxs + 1]; #define idx(v) (v <= lim ? le[v] : ge[global_n / v]) void sieve(const int &n) { rep(i,2,n){ if(!lpf[i]){ lpf[i]=++pcnt; pri[lpf[i]]=i; spri[pcnt]=sum(spri[pcnt-1],1);// } for(int j=1,v;j<=lpf[i];j++){ v=i*pri[j]; if(v>n)break; lpf[v]=j; } } } void init(const int &n,int _k,int _d){//calc Fprime global_n=n; K=_k;d=_d; cnt=0; for(ll i=1,j,v;i<=n;i=n/j+1){ j=n/i;v=j%MOD; lis[++cnt]=j; (j<=lim?le[j]:ge[n/j])=cnt; G[cnt][0]=sub(v,1ll);// } rep(k,1,pcnt){ const int p=pri[k]; const ll sqrp=sqrll(p); for(int i=1;lis[i]>=sqrp;i++){ const ll v=lis[i]/p; const int id=idx(v); dec(G[i][0],sub(G[id][0],k-1)); } } rep(i,1,cnt)Fprime[i]=(ll)G[i][0]*C(K+d,d)%MOD;// } int fp(const int &p,const int &c){return C(c*K+d,d);}// int F(const int &k,const ll &n){ if(pri[k]>n||n<=1)return 0; const int id=idx(n); int ans=sub(Fprime[id],(ll)spri[k-1]*C(K+d,d)%MOD);// for(int i=k;i<=pcnt&&sqrll(pri[i])<=n;i++){ long long pw=pri[i],pw2=sqrll(pw); for(int c=1;pw2<=n;c++,pw=pw2,pw2*=pri[i]) add(ans,((ll)fp(pri[i],c)*F(i+1,n/pw)+fp(pri[i],c+1))%MOD); } return ans; } } int main(){ fastio; int tc;cin>>tc; init(); Min25::lim=sqrt(1e9); Min25::sieve(Min25::lim+1000); while(tc--){ int n,k,d; cin>>n>>k>>d; Min25::init(n,k,d); cout<<(Min25::F(1,n)+1)%MOD<<endl; } return 0; }
分类:
数论
, CodeForces
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律