Loading

CSP 后多校十一

NOIP2018

感觉不是很难,一开始想的是二分最多能选多少个物品,然后一元二次函数直接 \(O(1)\) 出结果.

但是被卡精度了,其实只用二分每个物品最多花多少钱,画两个一元二次函数就行了.

因为两个物品的花费越接近越优,于是就完了.

CSP 2019

多项式不会.

CSP 2020

考场上想到可能是数位\(dp\),也想到可能是大点和小店是要分开做的,但是没想到要把两个结合起来..

发现 \(n>12\) 的情况和 \(n\le 12\) 的情况可以分开做,原因是 \(1+\dfrac{n^3}{9}+C(\dfrac{n^3}{9},2)\ge n^4\).

所以小点数位 \(dp\),直接暴力 \(O(n^2)\) 走,大点直接枚举就可以了.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long 
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
		for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
		for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
		return cit?(-w):w;
	};
} using namespace BSS;

const int N=2e3+21;

int m,n,mod,ans,os,osm,bs;
int ret[10]={0,1,161,6966,59899897};
int pos[N];
int dp[N][N];
auto ksm=[](int a,int b,int c,int w=1)->int{
	for(a%=c;b;b>>=1,a=a*a%c) if(b&1) w=w*a%c;
	return w%c;
};
auto PreWork=[]()->void{
	dp[0][0]=1;
	for(int i=0;i<=1800;i++){
		for(int j=1;j<=1800;j++){
			for(int k=0,lmk=min(i,9ll);k<=lmk;k++)
				dp[i][j]=dp[i][j]+dp[i-k][j-1];
		}
	}
};
auto SpWork=[](int x)->void{
	int l=1,r=1800,mid,res,smx=pow(x,3),por=smx*x,now=0; ans=0;
	while(l<=r){
		mid=(l+r)>>1; 
		if(dp[smx][mid]>=por or dp[smx][mid]<0) r=mid-1,res=mid;
		else l=mid+1;
	}
	for(int i=1;i<res;i++) now+=dp[smx][i]-dp[smx][i-1];
	for(int i=1,lft=smx;i<=res;i++){
		for(int j=(i==1),flag=1;j<=9 and flag;j++){
			if(now+dp[lft-j][res-i]>=por) flag=0,pos[i]=j,lft-=j;
			else now+=dp[lft-j][res-i];
		}
	}
	for(int i=1;i<=res;i++) ans=(ans+ksm(10,res-i,mod)*pos[i]%mod)%mod;
	printf("%lld ",ans); return void();
};
auto Work=[](int x)->void{
	int smx=pow(x,3),por=smx*x,now=smx%9+2,cnt=smx/9;
	ans=now; if(ans>9) ans=(ans%9*10+9)%mod; 		
	for(int i=1,lmi=cnt/os;i<=lmi;i++) ans=(ans*osm+bs)%mod;
	for(int i=1,lmi=cnt%os;i<=lmi;i++) ans=(ans*10ll+9)%mod;
	por-=1+cnt,cnt+=(now>9);
	for(int i=1;i<=cnt;i++){
		if(por<=cnt-i+1){
			ans=(ans-ksm(10,cnt-i,mod)-ksm(10,cnt-i+1-por,mod)+mod*2)%mod;
			return printf("%lld ",ans),void();
		}
		por-=(cnt-i+1);
	}
};
signed main(){
	File(number);
	n=read(),mod=read(); PreWork();	
	os=40000,osm=ksm(10,os,mod);
	for(int i=1;i<=os;i++) bs=(bs*10+9)%mod;
	for(int i=1,lmi=min(n,12ll);i<=lmi;i++) SpWork(i);
	for(int i=13;i<=n;i++) Work(i);
	exit(0);
}

NOIP 2021

原根不会.

posted @ 2021-11-10 06:20  AaMuXiiiiii  阅读(50)  评论(0编辑  收藏  举报