列表

详情


NC20271. [SCOI2009]游戏

描述

windy学会了一种游戏。对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应。最开始windy把数字按顺序1,2,3,……,N写一排在纸上。然后再在这一排下面写上它们对应的数字。然后又在新的一排下面写上它们对应的数字。如此反复,直到序列再次变为1,2,3,……,N。 
如: 1 2 3 4 5 6 对应的关系为 1->2 2->3 3->1 4->5 5->4 6->6 
windy的操作如下 
1 2 3 4 5 6 
2 3 1 5 4 6 
3 1 2 4 5 6 
1 2 3 5 4 6 
2 3 1 4 5 6 
3 1 2 5 4 6 
1 2 3 4 5 6 
这时,我们就有若干排1到N的排列,上例中有7排。现在windy想知道,对于所有可能的对应关系,有多少种可能的排数。

输入描述

包含一个整数N,1 ≤ N ≤ 1000

输出描述

包含一个整数,可能的排数。

示例1

输入:

3

输出:

3

示例2

输入:

10

输出:

16

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 3ms, 内存消耗: 1692K, 提交时间: 2020-10-06 09:48:08

#include<iostream>
#include<cstdio>
using namespace std;
int n,t,p[1001];
long long ans,f[1001][1001];
bool ff[1001];
void get()
{
    for(int i=2;i<=1000;i++)
    {
      if(!ff[i])p[++t]=i;
      for(int j=1;j<=t&&i*p[j]<=1000;j++){ff[i*p[j]]=true;if(i%p[j]==0 )break; }
    }
}
void dp()
{
    f[0][0]=1;
    for(int i=1;i<=t;i++)
    {
      for(int j=0;j<=n;j++)f[i][j]=f[i-1][j];
      for(int j=p[i];j<=n;j*=p[i])
        for(int k=0;k<=n-j;k++)
           f[i][k+j]+=f[i-1][k];
    }
}
int main()
{
    cin>>n; 
    get();
    dp();
    for(int i=0;i<=n;i++)ans+=f[t][i];
    cout<<ans<<endl;
}

C++11(clang++ 3.9) 解法, 执行用时: 3ms, 内存消耗: 380K, 提交时间: 2020-09-27 11:07:16

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int i,j,k,n,L=0,T[505];
    long long ans=0,DP[1005]={0};
    bool V[1005]={0};
    for(i=2;i<=1e3;i++)
    {
    	if(!V[i])T[L++]=i;
    	for(j=0;j<L&&i*T[j]<=1e3;j++)V[i*T[j]]=1;
	}
    scanf("%d",&n),DP[0]=1;
    for(i=0;i<L;i++)
    	for(j=n;j>=T[i];j--)
    		for(k=T[i];k<=j;k*=T[i])DP[j]+=DP[j-k];
    for(i=0;i<=n;i++)ans+=DP[i];
    printf("%lld\n",ans);
    return 0;
}

上一题