CF 757E Bash Plays with Functions——积性函数+dp+质因数分解

题目:http://codeforces.com/contest/757/problem/E

f0[n]=2^m,其中m是n的质因子个数(种类数)。大概是一种质因数只能放在 d 或 n/d 两者之一。

然后应该发现因为 f0 是积性的,所以 fr 也是积性的!因为是卷积得来的。

这样就能把每个质因数分开。对于每种质因数考虑 fr 的转移,则 f [ r ][ p^k ] = sigma(i:0~k) ( f [ r-1 ][ p^i ] ) 。

应该发现 f0 里每种质因数的值只和其次数有关,从转移可得出 f [ k ] 里的各种质因数的值也只和其次数有关!所以 dp 状态里只要记录次数就行。

学习到了质因数分解的更好而同样简单的方法。就是预处理mindiv,然后每次除以自己的mindiv。

先写了自己的原始方法,T了;于是怒写了个pollar rho,结果T得更快,难道是写错了?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e6,M=20,mod=1e9+7;
int q,r,n,dp[N+5][M+5],s[M+5],ans,mindiv[N+5],cnt,pri[N+5];
bool vis[N+5];
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
void upd(int &x){x-=(x>=mod?mod:0);}
void init()
{
  mindiv[1]=1;//
  for(int i=2;i<=N;i++)
    {
      if(!vis[i])pri[++cnt]=i,mindiv[i]=i;
      for(int j=1;j<=cnt&&(ll)i*pri[j]<=N;j++)
    {
      int d=i*pri[j];
      vis[d]=1; mindiv[d]=pri[j];
      if(i%pri[j]==0)break;
    }
    }
}
int pw(int x,int k,int md)
{
  int ret=1;while(k){if(k&1)ret=(ll)ret*x%md;x=(ll)x*x%md;k>>=1;}return ret;
}
bool MR(int x)
{
  if(x==2)return true;
  int s=20,u=x-1,t=0;
  while((u&1)==0)u>>=1,t++;
  while(s--)
    {
      int a=rand()%(x-2)+2;//2~x-1
      a=pw(a,u,x);
      for(int i=1,d;i<=t;i++)
    {
      d=(ll)a*a%x;
      if(d==1&&a!=1&&a!=x-1)return false;
      a=d;
    }
      if(a!=1)return false;
    }
  return true;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int Pl_rho(int x,int c)
{
  int x0=rand()%x,y=x,t=1,k=0;
  while(1)
    {
      x0=((ll)x0*x0+c)%(x+1);
      int g=gcd(abs(x0-y),x);
      if(g!=1&&g!=x)return g;
      if(x0==y)return x;
      if(++k==t)t<<=1,y=x0;
    }
}
void fd_fc(int x)
{
  if(x<2)return;
  if(MR(x))
    {
      int ret=0;
      while(n%x==0)n/=x,ret++;
      ans=(ll)ans*dp[r][ret]%mod;
      return;
    }
  int p=x;
  while(p==x)p=Pl_rho(p,rand()%(x-1)+1);//1~x-1
  fd_fc(p); fd_fc(x/p);
}
int main()
{
  dp[0][0]=1;s[0]=1; init();
  for(int i=1;i<=M;i++)dp[0][i]=2,s[i]=s[i-1]+2;
  for(int i=1;i<=N;i++)
    for(int j=0;j<=M;j++)
      dp[i][j]=s[j],s[j]=s[j-1]+dp[i][j],upd(s[j]);
  q=rdn();
  while(q--)
    {
      r=rdn(); n=rdn(); ans=1;
      //fd_fc(n);
      while(n!=1)
    {
      int i=mindiv[n],d=0;
      while(n%i==0)n/=i,d++;
      ans=(ll)ans*dp[r][d]%mod;
    }
      /*
      for(int i=mindiv[n],d;(ll)i*i<=n;i++)
    if(n%i==0)
      {
        d=0;
        while(n%i==0)d++,n/=i;
        ans=(ll)ans*dp[r][d]%mod;
      }
      if(n>1)ans=(ll)ans*dp[r][1]%mod;
      */
      printf("%d\n",ans);
    }
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/9776781.html