其他分享
首页 > 其他分享> > noip模拟47

noip模拟47

作者:互联网

T1

先筛出\([2,min(\sqrt r,k)]\)里的质数,再用它们在\([max(l,2*p),r]\)里打标记,没标记的是类素数

筛到\(\sqrt r\) 就可以枚举到r的所有素数,所以取\(min(\sqrt r,k)\),复杂度就到\(O(\sqrt r \log\log n)\)

可以看出在筛出小区间的大素数上,埃氏筛比线性筛更易操作

T2

设\(dp[i]\)表示以i结尾的子序列个数,转移方程

\[dp[i]=\sum _{j=1}^{n}dp[j]+1 \]

因为可以在每个序列的末尾加个i,同时i自己单独算个子序列

当下一个元素不确定时,最优选择是选dp值最小的转移,因为方程可以写成

\[dp[i]=\sum_{j=1,j!=1}^{n}dp[j]+dp[i]+1 \]

相当于将其他dp加起来怼到一个dp上,为了时方案数尽量多,肯定是其他的dp加起来尽量大,那就是选当前最小dp转移

在前n个转移完了之后,要做的就是选当前dp最小的,填上所有dp的和+1,然后它就变成了最大的,这个过程可以用矩阵快速幂实现

注意求完前n个的方案数后要排序,不能直接sort,因为要取模,所以按最晚出现的位置排序

代码

T1

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e7+11;
bool jud[N];
bool fp[N];
int p[N];
int num;
int l,r,k;
int sqr;
void get_prime()
{
	fp[1]=1;
	fp[0]=1;
	sqr=min(sqr,k);
	for(int i=2;i<=sqr;i++)
	{
		if(!fp[i])
			p[++num]=i;
		for(int j=1;j<=num&&p[j]*i<=sqr;j++)
		{
			fp[p[j]*i]=1;
			if(i%p[j]==0)
				break;
		}
	}
	return;
}
void get_ans()
{
	for(int i=1;i<=num;i++)
	{
		int st=max(l/p[i],2ll);
		int ed=r/p[i];
		for(int j=st;j<=ed;j++)
			jud[j*p[i]-l]=1;
	}
	return;
}
signed main()
{
	cin>>l>>r>>k;
	sqr=sqrt(r);
	get_prime();
	get_ans();
	int ans=0;
	for(int j=0;j<=r-l;j++)
		if(!jud[j])
			ans^=(l+j);
	cout<<ans<<endl;
	return 0;
}

T2

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+11;
const long long mod=1e9+7;
struct mat_{
	long long mat[102][102];
	int h,l;
}x,as,c;
struct dp_{
	int sum,last;
	friend bool operator<(dp_ a,dp_ b)
	{
		return a.last<b.last;
	}
}f[N];
long long n,m,k;
int a[N];
int last[N];
inline long long read()
{
	long long s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')
		ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
void fma()
{
	as.l=k+1;
	as.h=k+1;
	for(int i=1;i<=k-1;i++)
		as.mat[i][i+1]=1;
	for(int i=1;i<=k+1;i++)
		as.mat[k][i]=1;
	as.mat[k+1][k+1]=1;
	long long y=m;
	while(y)
	{
		if(y&1)
		{
			c.h=as.h;
			c.l=x.l;
			for(int i=1;i<=as.h;i++)
				for(int j=1;j<=x.l;j++)
				{
					long long s=0;
					for(int k=1;k<=as.l;k++)
						s+=as.mat[i][k]*x.mat[k][j]%mod;
					c.mat[i][j]=s%mod;
				}
			x=c;
		}
		c.h=as.h;
		c.l=as.l;
		for(int i=1;i<=as.h;i++)
			for(int j=1;j<=as.l;j++)
			{
				long long s=0;
				for(int k=1;k<=as.l;k++)
					s+=as.mat[i][k]*as.mat[k][j]%mod;
				c.mat[i][j]=s%mod;
			}
		as=c;
		y>>=1;
	}
	return;
}
signed main()
{
	long long ans=0;
	n=read();
	m=read();
	k=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	long long sum=0;
	for(int i=1;i<=n;i++)
	{
		long long maxn=f[a[i]].sum;
		f[a[i]].sum=(sum+1)%mod;
		sum=(f[a[i]].sum+sum-maxn+mod)%mod;
		f[a[i]].last=i;
	}
	sort(f+1,f+k+1);
	x.h=k+1;
	x.l=1;
	for(int i=1;i<=k;i++)
		x.mat[i][1]=f[i].sum;
	x.mat[k+1][1]=1;
	fma();
	for(int i=1;i<=k;i++)
		ans=(ans+x.mat[i][1])%mod;
	cout<<ans%mod<<endl;
	return 0;
}

标签:const,noip,int,47,long,sqr,模拟,sqrt,dp
来源: https://www.cnblogs.com/sitiy/p/15183294.html