预期 | 一测 | Δ \Delta Δ | |
---|---|---|---|
自然数拆分 | 100 | 0 | -100 |
反素数 | 100 | 100 | 0 |
越狱 | 100 | 100 | 0 |
佳佳的 Fibonacci | 100 | 100 | 0 |
矿场搭建 | 0 | 0 | 0 |
总分 | 400 | 300 | -200 |
自然数拆分
法一:
n 为4000的数据使得此题n2可做,用dp[i][j]表示将i分为k个数,考虑转移,
对于以 1 开头的方案,等于 i-1 的方案数,对于不 1 开头的方案,可视为 i-k
的所有方案的数都加上 1 。所以可得dp转移方程
d
p
(
i
,
j
)
=
d
p
(
i
−
1
,
j
−
1
)
+
f
(
i
−
j
,
j
)
\ dp(i,j)= dp(i-1,j-1)+f(i-j,j)
dp(i,j)=dp(i−1,j−1)+f(i−j,j)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int f[4001][4001];
int n,ans;
int main(){
f[0][0]=1;
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=i;++j)
f[i][j]=((ll)f[i-1][j-1]+(ll)f[i-j][j])%2147483648u;
for(int i=2;i<=n;++i)
ans=((ll)ans+(ll)f[n][i])%2147483648u;
printf("%d",ans);
}
法二 : 背包
unsigned int f[N];
memset(f,0,sizeof(f));
f[0]=1;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
f[j]=(f[j]+f[j-i])%2147483648u;
cout<<(f[n]>0 ? f[n]-1 : 2147483647)<<end;
反素数
1 : N以内最大的反素数,就是1~N中约数个数最多的一批数中最小的个。
2 : 反素数的质因数从2开始,指数一定递减(要最小)。
由1 2 得 3 : 反素数最大的质因子只有可能到29 (2连乘到29已超long long),且
指数总和不可能超过30 (230大于2*109)。
所以可以dfs依次确定2~29的指数,并满足指数单调递减,总乘积不超过n,实时更新答案就行了。
#include <iostream>
#define ll long long
using namespace std;
ll n,p[11]={0,2,3,5,7,11,13,17,19,23,29},c[11];
ll ans=0x7f7f7f7f,cnt=1;
void dfs(ll x,ll num,ll cnt0){
if(x==11){
if(cnt0>cnt || cnt0==cnt && ans>num)
cnt=cnt0,ans=num;
return;
}
ll num0=num;
for (int i=0;i<=c[x-1];i++){
if(num0>n) return;
c[x]=i;
dfs(x+1,num0,cnt0*(i+1));
num0*=p[x];
}
}
int main() {
scanf("%d",&n);
c[0]=33;
dfs(1,1,1);
printf("%lld",ans);
return 0;
}
越狱
正难则反,ans=mn-m
×
\times
×(m-1)n-1;
记得快速幂。
佳佳的 Fibonacci
前置芝士 :Sn=Fn+2 - 1(累加法易证)
易得Tn=(Sn-S0+Sn-S1+···+Sn-Sn-1)=n
×
\times
×Fn+2-(F2+····+Fn+1)=n
×
\times
×Fn+2-(Sn+1-F1)=n
×
\times
×Fn+2-(Fn+3)+2
好了现在只要求出Fn+2和Fn+3就行了。
递推
O
(
n
)
O(n)
O(n)显然过不了,就需要用矩阵乘法。
由Fn只与Fn-1和Fn-2有关设
F
(
n
)
F(n)
F(n) 表示一个 1
×
\times
× 2 的矩阵
,
F
(
n
)
F(n)
F(n)=[Fn Fn+1];
F
(
n
−
1
)
F(n-1)
F(n−1)=[Fn-1 Fn];为了根据
F
(
n
−
1
)
F(n-1)
F(n−1)得到
F
(
n
)
F(n)
F(n)
要使
F
(
n
−
1
)
F(n-1)
F(n−1)第 1,2 列上的数都累加到
F
(
n
)
F(n)
F(n) 的第 2 列上,
F
(
n
−
1
)
F(n-1)
F(n−1)第 2 列上的数作为
F
(
n
)
F(n)
F(n) 的第 1 列,因此令矩阵
A
=
[
0
1
1
1
]
F
(
0
)
=
[
0
1
]
A= \left[ \begin{matrix} 0 & 1 \\ 1 & 1 \end{matrix} \right] F(0)= \left[ \begin{matrix} 0 & 1 \end{matrix} \right]
A=[0111]F(0)=[01]
目标为
F
(
n
+
2
)
=
F
(
0
)
×
A
n
+
2
F(n+2)=F(0)\times A^{n+2}
F(n+2)=F(0)×An+2,其中
F
(
n
+
2
)
F(n+2)
F(n+2)的第一项即为Fn+2,第2项即为Fn+3。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod;
ll n,f[2],a[2][2];
void mul(ll f[2],ll a[2][2]) {
ll c[2];
memset(c,0,sizeof(c));
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
c[j]=(c[j]+f[k]*a[k][j]%mod)%mod;
memcpy(f,c,sizeof(c));
}
void mulself(ll a[2][2]) {
ll c[2][2];
memset(c,0,sizeof(c));
for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
for(int k=0; k<2; k++)
c[i][j]=(c[i][j]+a[i][k]*a[k][j]%mod)%mod;
memcpy(a,c,sizeof(c));
}
ll ans;
int main() {
scanf("%d%d",&n,&mod);
ll f[2]= {0,1};
ll a[2][2]= {{0,1},{1,1}};
for(ll x=n+2ll;x;x>>=1) {
if(x&1) mul(f,a);
mulself(a);
}
ans=n*f[0]-f[1]+2ll;
ans=(ans%mod+mod)%mod;
printf("%lld",ans);
}