luogu P4161 [SCOI2009]游戏

传送门

我们发现整个大置换中,会由若干形如(a1a2,a2a3,...an1an,ana1)的循环置换组成,记某个循环置换中元素个数为mi而整个置换的循环节大小为lcm(m1,m2,...),那么问题转化成把一个数n拆成若干整数之和,问拆出来的整数的lcm有多少种

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

考虑dp,设fin=i时的答案,然后依次枚举质数,因为当前考虑的质数之前没考虑,所以fi可以从fipj,fipj2,fipj3...转移过来,这其实就是个背包

详见代码

#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;
}
posted @   ✡smy✡  阅读(95)  评论(0编辑  收藏  举报
编辑推荐:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示