测试67。好题。数学,打表,fibonacci树规律。

TO1打表。

   P1:   T3为了小点跑得快没取mod

      但是打表的时候忘了加取mod少了20分。

注意1检查要把题目要求过一遍。

2、打表注意暴力在大数据点下是否正确。

P2:分块打表。例:以500为块长,%500的部分跑暴力。

要灵活。

2:做题顺序。

1T2,显然最水的可以先做。

2T1T3暴力。

3T1去想正解。

3:态度。要去尽力拿分,从可能的地方找切入点。

T1:数学题。注意莫比乌斯函数不是联赛考点。

考试时状态不太好,态度不够认真

没想到((x,S)=1)==((x,S-x)==1)。发现一些性质。等效。

1、更换枚举顺序。第一层sigma放到第二层可以O(1)算。Sigma式更换顺序。

2、考虑实际含义。

T2最简单的。树状数组维护LIS长度及方案数。

T3fibonacci树。

1、观察规律。一个黑点的第i层子节点中白点个数为fib(i)

2、等效。斐波那契树的子部分都是等效的。重复部分来源于等效。

这样的话每个等效部分只枚举一次,再乘上等效个数即可。

 

 

T1思路整理:n<=1e14->sqrt()

a+b<=n&&(a+b)|ab;

a=d*x,b=d*y;

d*(x+y)|d*d*x*y

(x+y)|d*x*y

And  (x,y)==1->x+y|d

Ans=sigma:d(1,n)*x(1,n/d)*y(1,n.d-x),[(x,y)=1,x+y|d]

一种其他思路:d*(1,n)*D*u(D)*x’*y’.

D=gcd(x,y)

但是不可写,是错的。

1、考虑实际含义。2x+y往往可以变为x,S-x

S=x+y,((x,y)=1)==((x,S)=1)

更相减损可证。

则枚举x,y转化为求ou(S).  把枚举转化为可以预处理或者直接O(1)算的式子,函数。

Ans=sigma:d(1,n)*S(S|d)*ou(S)&&d*S<=n  S<d,S*S<=n,Ssqrt级别。

 

外层O(n),且内层约数sqrt。这个很难做,

分析正解sqrt级别。

更换枚举顺序。发现S<=sqrt(n);

直接变枚举约数为倍数,把S放到前面。

{S*d<=n,S|d}->sigma:d =n/(S^2)

 

Ans=sigma:S(1,sqrt(n)*ou(S)*(n/(S^2));

下面是下发题解和我的代码。

#include<bits/stdc++.h>
#define F(i,a,b) for(rg int i=a;i<=b;++i)
#define LL long long
#define rg register
#define pf(a) printf("%d ",a)
#define phn puts("")
using namespace std;
#define int LL
#define N 10000010
int n,t;
LL ans;
int prm[N/10],cnt,ou[N];
signed main(){
    scanf("%lld",&n);
    t=sqrt(n);
    F(i,2,t){
        if(!ou[i]){
            ou[i]=i-1;prm[++cnt]=i;
        }
        for(int j=1;j<=cnt&&i*prm[j]<=t;++j){
            if(i%prm[j]==0){
                ou[i*prm[j]]=ou[i]*prm[j];break;
            }
            else {
                ou[i*prm[j]]=ou[i]*ou[prm[j]];
            }
        }
    }
    F(i,1,t){
        ans=(ans+ou[i]*(n/(i*i)));
    }
    printf("%lld\n",ans);
}
/*
g++ 1.cpp -g 
time ./a.out
21
*/
T1
#include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define LL long long
#define pf(a) printf("%d ",a)
#define phn puts("")
using namespace std;
/** mod*/
#define int LL
int n,type;
#define N 100500
int a[N];
const int mod=123456789;
const int maxn=1e5+10;
int w[N],s[N];
int MO(int x){return x<mod?x:x-mod;}
void add(int x,int l,int c){
    for(;x<=maxn;x+=x&-x){
        if(w[x]<l){
            w[x]=l;s[x]=c;
        }
        else if(w[x]==l){
            s[x]=MO(s[x]+c);
        }    
    }    
}
LL l,c;
void ask(int x){
    l=0;c=0;
    for(;x;x-=x&-x){
        if(w[x]>l){
            l=w[x];c=s[x];
        }
        else if(w[x]==l){
            c=MO(c+s[x]);
        }    
    }
}
signed main(){
    scanf("%lld%lld",&n,&type);
    F(i,1,n)scanf("%lld",&a[i]);
    a[n+1]=1e5+1;
    add(1,0,1);
    F(i,1,n){
        ask(a[i]);
        add(a[i]+1,++l,c);
    }
    ask(a[n+1]);
    printf("%lld\n",l);
    if(type)printf("%lld\n",c);
}
/*
g++ 2.cpp -g
./a.out
5 1
1 3 2 5 4
*/
T2
#include<cstdio>
#include<iostream>
#include<vector>
#define rg register
#define F(i,a,b) for(rg int i=a;i<=b;++i)
#define LL long long
#define pf(a) printf("%d ",a)
#define phn puts("")
using namespace std;
int n;
#define N 200010
const int mod=123456789;
LL len[10010];
LL f[N],g[N];
int max(int x,int y){return x>y?x:y;}
signed main(){
    scanf("%d",&n);
    f[1]=1;g[1]=1;F(i,2,n)(g[i]=g[i-1]+(f[i]=(f[i-1]+f[i-2])%mod))%=mod;
    F(i,2,n-1)len[i]=(len[i]+f[i-1]*(g[max(n-i-2,0)]+1))%mod;
    F(j,2,n-2)len[j+1]=(len[j+1]+f[j-1]*g[n-j-1])%mod;
    F(i,3,n-2){
        F(j,2,n-2){
            (len[i+j]+=f[i-2]*f[j-1]%mod*g[n-max(i,j)-1])%=mod;
        }
    }
    F(i,1,n<<1)printf("%lld ",len[i]);phn;
}
/*
g++ 3.cpp -g  
time ./a.out
20
*/
T3

 

 

posted @ 2019-10-10 17:31  seamtn  阅读(170)  评论(1编辑  收藏  举报