千钧一发-双十

一点点总结:

干了点什么。

关于考试……废在T1上了:-(

T1打了半天表,找了$\Theta(N\sqrt{N})$的方法,得了少的可怜的$40$

T2感受出了$dp$和线段树的味道但是只是打了个暴力。

T3打个暴力丟上去骗了点分。

要做什么。

先看看三道题……这回忘了看把我搞死了。

不重要的:找规律想想$\phi(x)$

有了什么。

32
Miemeng 40
03:07:34
40
03:07:34
40
03:07:34
120
03:07:34

黄唧唧的分数……

题解(差点咕掉

T1

不打表了,试图用题解的法子证一证。(完全是在口胡,可以看这个大神的:%%%

首先点对满足

$$a+b \mid ab$$

我们记$a$和$b$的$gcd$为$d$

有:

$$(a'+b')d \mid a'b' d^2$$

于是约去一个$d$

$$a'+b' \mid a'b' d$$

因为

$$
a' \not\mid b' \\
a' \not\mid d \\
a' \not\mid b'
$$

$$a'+b' \mid d \\ a'+b' \not\mid a'$$

于是可以直接枚举$a'+b'$来判断合法性。

因为$a+b\leq n $且$d\geq a'+b'$

于是在每个$a'+b'\leq \sqrt{n}$下只有$\phi(a'+b')$个合法解

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define LL long long
#define sqN 11111111
using namespace std;
int phi[sqN];
bool not_p[sqN];
vector<int> prm;
LL ans,n;
void prerun(){//getphi
	const int lim=10000000;
	phi[1]=0;
	for(int i=2;i<=lim;i++){
		if(!not_p[i]){
			prm.push_back(i);
			phi[i]=i-1;
		}
		for(int j=0;j<prm.size();j++){
			if(i*prm[j]>lim)break;
			not_p[i*prm[j]]=1;
			if(i%prm[j]==0){
				phi[i*prm[j]]=phi[i]*prm[j];
				break;
			}
			else phi[i*prm[j]]=phi[i]*(prm[j]-1);
		}
	}
}
int main(){
//	freopen("1.in" ,"r",stdin);\
	freopen("2.out","w",stdout);
	prerun();
	scanf("%lld",&n);
	for(LL i=1;i*i<=n;i++)
		ans+=n/(i*i)*phi[i];
	printf("%lld\n",ans);
}

T2

线段树优化$dp$,可以直接二元组$dp$出结果。

#include <iostream>
#include <cstring>
#include <cstdio>
#define N 111111
#define LL long long

using namespace std;

const int Mod=123456789,maxR=100011;
struct DP{
	int len;
	LL ans;
	DP(){len=ans=0;}
	DP(int a,LL b):len(a),ans(b){}
};
struct XDS{
	int l,r;
	DP dat;
#define lc(k) ((k)<<1)
#define rc(k) ((k)<<1|1)
}rt[N*4];
int rn,typ,arr[N];
DP Max(const DP &a,const DP &b){
	if(a.len>b.len)return a;
	if(a.len<b.len)return b;
	return DP(a.len,(a.ans+b.ans)%Mod);
}
void build(int k,int l,int r){
	rt[k].l=l,rt[k].r=r;
	rt[k].dat=DP(0,0);
	if(l==r)return ;
	int mid=(l+r)/2;
	build(lc(k),l    ,mid);
	build(rc(k),mid+1,r);
}
void change(int k,int id,DP v){
	if(rt[k].l==rt[k].r){
		rt[k].dat=Max(rt[k].dat,v);
		return ;
	}
	int mid=(rt[k].l+rt[k].r)>>1;
	if(mid>=id)
		change(lc(k),id,v);
	else
		change(rc(k),id,v);
	rt[k].dat=Max(rt[lc(k)].dat,rt[rc(k)].dat);
}
DP query(int k,int l,int r){
	if(l<=rt[k].l && rt[k].r<=r)
		return rt[k].dat;
	DP nw;
	int mid=(rt[k].l+rt[k].r)>>1;
	if(mid>=l)
		nw=Max(nw,query(lc(k),l,r));
	if(mid<r)
		nw=Max(nw,query(rc(k),l,r));
	return nw;
}
int main(){
//	freopen("1.in" ,"r",stdin );\
	freopen("1.out","w",stdout);
	scanf("%d%d",&rn,&typ);
	for(int i=1;i<=rn;i++){
		scanf("%d",arr+i);
		arr[i]++;
	}
	build(1,1,maxR);
	for(int i=1;i<=rn;i++){
		DP fw=query(1,1,arr[i]-1);
		change(1,arr[i],Max(DP(fw.len+1,fw.ans),DP(1,1)));
	}
	DP res=query(1,1,maxR);
	printf("%d\n",res.len);
	if(typ)
		printf("%lld\n",res.ans);
}

T3

Fibonacci树……

分$LCA$枚举长度统计答案$\Theta(N^2)$

#include <iostream>
#include <cstring>
#include <cstdio>
#define N 5555
#define LL long long

using namespace std;
const int Mod=123456789;
LL dep,pre[N],fib[N],ans[N*2];
int main(){
	scanf("%lld",&dep);
	fib[1]=1,fib[2]=0;
	for(int i=3;i<=dep;i++)
		fib[i]=(fib[i-1]+fib[i-2])%Mod;
	for(int i=1;i<=dep;i++)
		pre[i]=(pre[i-1]+fib[i])%Mod;
	for(int i=1;i<dep;i++)
		ans[i]=(pre[dep-i]*fib[i+1])%Mod;
	for(int i=1;i<=dep;i++){
		for(int j=1;j<=dep;j++){
			int h=max(i,j);
			ans[i+j]+=((pre[dep-h+1]-1)*fib[i]%Mod*fib[j+1]%Mod)%Mod;
			ans[i+j]%=Mod;
		}
	}
	for(int i=1;i<=2*dep;i++)
		printf("%lld ",ans[i]);
	puts("");
}

 

posted @ 2019-10-12 10:37  Miemeng_麦蒙  阅读(142)  评论(2编辑  收藏  举报

小麦在雨中,蒙蒙的雾气

麦蒙不想有人骚扰他,如果有必要 联系 QQ:1755601414

如果你嫌广告大,那就喷我吧,不是博客园的锅。