[luogu4161 SCOI2009]遊戲 (DP)
阿新 • • 發佈:2018-10-02
現實 bool 傳送門 break int register solution str tdi
傳送門
Solution
可以發現實際上是把n分為幾個循環節,然後找循環節的\(lcm\)是這次的排數
而\(lcm\)必然是一些最高次冪的質數的成積,那麽就dp求一下所有情況就好了
PS:註意並不是必須要等於n小於n都行,因為可以在後面補1而\(lcm\)不變
Code
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define Re register #define int long long #define F(i,a,b) for(Re int i=(a);i<=(b);i++) #define R(i,a,b) for(Re int i=(b);i>=(a);i--) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();} while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar(); return x*f; } const int N=1010; bool vis[N]; int n,tot,ans; int pri[N],f[N]; void init() { F(i,2,n) { if(!vis[i]) pri[++tot]=i; for(Re int j=1;j<=tot&&i*pri[j]<=n;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0) break; } } } signed main() { n=read(); init(); // F(i,1,tot) printf("%d ",pri[i]);cout<<endl; f[0]=1; F(i,1,tot) R(j,0,n) for(Re int k=pri[i];j+k<=n;k*=pri[i]) f[j+k]+=f[j]; F(i,0,n) ans+=f[i]; printf("%lld",ans); return 0; }
[luogu4161 SCOI2009]遊戲 (DP)