zoukankan      html  css  js  c++  java
  • SCOI2009游戏 (数论+dp)

    题解

    很显然,对于一个确定的排列,每个数字的移动规则是一定的,我们根据这个排列,把它抽象为i向a[i]连一条边,很显然最后会构成一个环,那么行数就是这些环长的lcm。

    那么问题变成了把n任意进行划分,求它们能够组成的lcm的个数。

    我们发现,只有素数会对答案有影响,所以我们就对每个素数以及它们的幂跑一边01背包,最后统计答案即可。

    代码

    #include<iostream>
    #include<cstdio>
    #define N 1009
    using namespace std;
    long long dp[N][N],prime[N],vis[N],n,tot,k;
    int main()
    {
      scanf("%d",&n);
      for(int i=2;i<=n;++i)
        {
            if(!vis[i])prime[++tot]=i;
            for(int j=1;j<=tot&&(k=i*prime[j])<=n;++j)
              {
                  vis[k]=1;if(i%prime[j]==0)break;
              }
        }
        dp[0][0]=1;
      for(int i=1;i<=tot;++i)
      {
        for(int j=0;j<=n;++j)dp[i][j]=dp[i-1][j];
        for(int j=prime[i];j<=n;j*=prime[i])
           for(int k=0;k+j<=n;++k)
             dp[i][j+k]+=dp[i-1][k];
      }
      long long ans=0;
      for(int i=0;i<=n;++i)ans+=dp[tot][i];
      cout<<ans; 
      return 0;
    }
  • 相关阅读:
    JSP的作用域与COOKIE
    jsp数据交互
    JSP基本使用方式
    分层架构的初步理解
    JDBC的基本应用
    HTML5新标签
    弹性布局
    解决js获取兄弟节点的兼容问题
    js去重函数(封装函数)
    封装日期函数
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9417761.html
Copyright © 2011-2022 走看看