9.26 test

预期一测 Δ \Delta Δ
自然数拆分1000-100
反素数1001000
越狱1001000
佳佳的 Fibonacci1001000
矿场搭建000
总分400300-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(i1,j1)+f(ij,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(n1)=[Fn-1 Fn];为了根据 F ( n − 1 ) F(n-1) F(n1)得到 F ( n ) F(n) F(n)
要使 F ( n − 1 ) F(n-1) F(n1)第 1,2 列上的数都累加到 F ( n ) F(n) F(n) 的第 2 列上, F ( n − 1 ) F(n-1) F(n1)第 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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值