zoukankan      html  css  js  c++  java
  • 千钧一发-双十

    一点点总结:

    干了点什么。

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

    T1打了半天表,找了$Theta(Nsqrt{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' otmid b' \
    a' otmid d \
    a' otmid b'
    $$

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

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

    因为$a+bleq n $且$dgeq 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
    ",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
    ",res.len);
    	if(typ)
    		printf("%lld
    ",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("");
    }
    
  • 相关阅读:
    C协程使用举例
    教你理解复杂的CC++声明(转)
    C语言学习趣事_关于指针转换
    Howard's Startup Game @meditic » 降级论
    认识C++语言关键字和语法extern和双冒号
    Linux操作系统的种种集成开发环境
    新建Android项目时使用project from existing source导入已经存在的项目报 AndroidManifest.xml file missing错误解决方案
    JAVA中IP和整数相互转化
    自定义Struts2实现
    Web编程所需的必要知识、环境工具相关
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/Exam20191010.html
Copyright © 2011-2022 走看看