码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P4161 [SCOI2009]游戏

时间:2018-10-17 22:11:01      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:mes   double   printf   www.   ace   return   tar   amp   表示   

传送门

我们发现整个大置换中,会由若干形如\((a_1\rightarrow a_2,a_2\rightarrow a_3,...a_{n-1}\rightarrow a_n,a_n\rightarrow a_1)\)的循环置换组成,记某个循环置换中元素个数为\(m_i\)而整个置换的循环节大小为\(lcm(m_1,m_2,...)\),那么问题转化成把一个数\(n\)拆成若干整数之和,问拆出来的整数的\(lcm\)有多少种

\([1,n]\)的质数筛出来,然后dfs,从前往后考虑质数\(p_i\),每次从剩余的数中减去\({p_i}^k\),假设某个时刻表示的数为\(s\),那么减去\({p_i}^k\)后就能表示\(s*{p_i}^k\),这样子计算是不重不漏的,但是无法通过此题(方案数为\(long\ long\)级别)

考虑dp,设\(f_i\)\(n=i\)时的答案,然后依次枚举质数,因为当前考虑的质数之前没考虑,所以\(f_i\)可以从\(f_{i-p_j},f_{i-{p_j}^2},f_{i-{p_j}^3}...\)转移过来,这其实就是个背包

详见代码

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-5)

using namespace std;
il LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int prm[200],tt,n;
char vis[1010];
il void init()
{
  for(int i=2;i<=n;i++)
    {
      if(!vis[i]) prm[++tt]=i;
      for(int j=1;j<=tt&&i*prm[j]<=n;j++)
        {
          vis[i*prm[j]]=true;
          if(i%prm[j]==0) break;
        }
    }
}
LL f[1010];
/*void dfs(int o,int s)
{
  if(o>tt||s<prm[o]) return;
  dfs(o+1,s);
  int xx=prm[o];
  while(s>=xx)
    {
      ++ans;
      dfs(o+1,s-xx);
      xx*=prm[o];
    }
}*/

int main()
{
  n=rd();
  init();
  for(int i=0;i<=n;i++) f[i]=1;
  for(int i=1;i<=tt;i++)
    for(int j=n;j>=0;j--)
      for(int k=prm[i];j-k>=0;k*=prm[i])
        f[j]+=f[j-k];
  printf("%lld\n",f[n]);
  return 0;
}

luogu P4161 [SCOI2009]游戏

标签:mes   double   printf   www.   ace   return   tar   amp   表示   

原文地址:https://www.cnblogs.com/smyjr/p/9807151.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!