ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

11.24 考试

2020-11-25 08:32:46  阅读:183  来源: 互联网

标签:int LL d% 11.24 1LL freopen include 考试


T4
求最长不下降子序列,因为最大值为150,并且数据产生方式有循环;
所以可以找规律,在后面的时候,每经过一个循环节答案最大值+1;
恶心的事循环节前面和后面的处理,很难调;

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
const int N=1e5+7;
LL n,tt,ans;
int t0,A,B,C,D,ff=0;
int vis[N],a[N],last[N];
LL f[N];
int main(){
	freopen("lis.in","r",stdin);
	freopen("lis.out","w",stdout);
	scanf("%lld",&n);
	scanf("%d%d%d%d%d",&t0,&A,&B,&C,&D);
	a[1]=t0;
	vis[a[1]]=1;
	last[a[1]]=1;
//	cout<<a[1]<<" ";
	for(int i=2;i<=n;i++){
		a[i]=1LL*(1LL*a[i-1]*a[i-1]*A+B*a[i-1]+C)%D;
		tt=i;
//		cout<<a[i]<<" ";
		if(vis[a[i]]){
			ff=1;
			break;
		}
		vis[a[i]]=1;
		last[a[i]]=i;
//		if(a[i]==9) cout<<"------"<<i<<" ";
	}
//	cout<<"\n";
//	cout<<tt<<"\n";
//	cout<<a[tt]<<"\n";
	LL l=last[a[tt]];
//	cout<<l<<"\n";
	if(ff==1) tt--;
	LL uu=tt-l+1;
//	cout<<uu<<"\n";
//	cout<<l<<" "<<"\n";
	LL ss=l-1+100*uu;
	for(int i=1;i<=min(ss,n);i++){
		if(i>tt) a[i]=1LL*(1LL*a[i-1]*a[i-1]*A+B*a[i-1]+C)%D;
		LL maxn=0;
		for(int j=1;j<i;j++){
			if(a[j]<=a[i]){
				maxn=max(maxn,f[j]);
			}
		}
		f[i]=maxn+1;
//		cout<<f[i]<<" ";
	}
	if(ff==0||ss>=n){
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++){
			if(i>tt) a[i]=1LL*(1LL*a[i-1]*a[i-1]*A+B*a[i-1]+C)%D;
			LL maxn=0;
			for(int j=1;j<i;j++){
				if(a[j]<=a[i]){
					maxn=max(maxn,f[j]);
				}
			}
			f[i]=maxn+1;
//			ans=max(ans,f[i]);
		}
		for(int i=1;i<=n;i++){
			ans=max(ans,f[i]);
		}
		cout<<ans;
		return 0;
	}
//	cout<<ss<<"\n";
	LL kk=n-ss;
//	cout<<kk<<"\n";
	LL oo=kk/uu;
	LL pp=0;
//	cout<<"--"<<oo<<"\n";
	if(oo!=0){
		oo--;
		pp=uu;
	}
//	cout<<(uu*99+l)<<"\n";
	for(int i=(uu*99+l);i<=ss;i++){
//		LL zz=(i-(l-1))/uu;
//		if((i-(l-1))%uu==0) zz--;
		f[i]+=oo;
//		cout<<f[i]<<" ";
	}
//	cout<<"\n";
//	cout<<f[1]<<"\n";
	LL yy=kk%uu;
//	cout<<yy<<"\n";
	pp+=yy;
//	cout<<pp<<"\n";
	for(int i=ss+1;i<=ss+pp;i++){
		if(i>ss) a[i]=1LL*(1LL*a[i-1]*a[i-1]*A+B*a[i-1]+C)%D;
		LL maxn=0;
		for(int j=1;j<i;j++){
			if(a[j]<=a[i]){
				maxn=max(maxn,f[j]);
			}
		}
		f[i]=maxn+1;
	}
	for(int i=1;i<=ss+pp;i++){
		ans=max(ans,f[i]);
	}
	cout<<ans;
	fclose(stdin);
	fclose(stdout);
	return 0; 
}
/*
309
126 139 23 135 26

707
77 56 129 57 131

10
1 1 3 5 37

1991
128 128 73 113 75

532889960237
143 88 122 1 147

1329
30 104 50 130 136
*/

T2
给定一个数组,可以选两个数a,b;
把a和b合并起来,就是a在前,b在后产生的一个新数;
问有多少种选的方案,使得拼起来的数不是k的倍数;

虑求有多少对(i; j)满足拼数结果为k的倍数。可以发现,对x; y拼数
的本质是x*10⌊log10y⌋+1+y(这个式子不严谨,明白意思就行)。只要加号
左边的与加号右边的对k取余的数能够加起来得到k或0即可。考虑
枚举j,设j的位数为dig=⌊log10aj⌋+ 1,那么只要查询有多少个数满足乘10dig的结果对k取余为k

#include<iostream>
#include<cstdio>
#include<map>
#define LL long long
using namespace std;
const int N=2e5+7;
int n,maxn;
LL k,ans;
LL a[N];
map<int,int> S[11];
int get(int x){
	int res=0;
	while(x!=0){
		res++;
		x/=10;
	}
	return res;
}
int main(){
	freopen("piece.in","r",stdin);
	freopen("piece.out","w",stdout);
	scanf("%d%lld",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		maxn=max(maxn,get(a[i]));
	}
	for(int i=1;i<=n;i++){
		int tt=a[i];
		for(int j=1;j<=maxn;j++){
			tt=1LL*tt*10%k;
			S[j][tt]++;
		}
	}
	for(int i=1;i<=n;i++){
		int tt=a[i];
		int nod=get(a[i]);
		for(int j=1;j<=nod;j++) tt=1LL*tt*10%k;
		S[nod][tt]--;
		if(a[i]%k){
			ans+=S[nod][k-a[i]%k];
		}else{
			ans+=S[nod][0];
		}
		S[nod][tt]++;
	}
	cout<<1LL*n*(n-1)-ans;
	fclose(stdin);
	fclose(stdout);
	return 0;
}
/*
4 11
45 1 10 12
*/

标签:int,LL,d%,11.24,1LL,freopen,include,考试
来源: https://www.cnblogs.com/Aswert/p/14033851.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有