【2019.9.15】

2019.9.15

summary

  • 时间安排不合理 大部分时间用在1、2题 第三题啥都没打成
  • 低级错误 空间开小了 而且最开始打的时候我都没有测第四组样例?!最后十几分钟发现第四组样例没过==
  • 基础不牢 加分二叉树这题我都没做过 gg
  • 浮躁

Candy

糖糖有一个整数A,设A的十进制表示为 \(a_1a_2a_3...a_n\);
定义 \(rotate(a_1a_2a_3...a_n)=a_2a_3...a_na_1\)
糖糖利用这个方法生成了n个数字串,其中:
\(b1=a,b2=rotate(b1),...,b_n=rotate(b_{n-1})\)
糖糖对于这些数字串在十进制下的和很感兴趣,现设 \(\sum{b_i}=S\)
她想知道S的最小非1的因子是多少

首先肯定先找下规律看看有没有规律,但是没用的.

不难发现最终的和的形式是\(sum\_digit(111111....1)\)的形式,其中\(sum\_digit\)表示所有数位的和.

所以无非答案就是\(sum\_digit\)的最小质因子或者是\(11111111..1\)的最小质因子

若最终答案不在\(sum\_digit\)里面的话呢,假设\(sum\_digit\)的最小质因子为\(x\)那么也就是说\(1111111...1\)里面存在一个质因子\(y\),\(y<x\)并且\(1111111...1\%y==0\)

考虑\(1111111...1=(10^n-1)/9\)(n表示有多少个1)

那么问题就转化成了\((10^n-1)/9%y==0\),我们可以枚举这个\(y\).因为和最大也就\(5e6\),所以\(y\)最多也不会超过\(5e6\),用线性筛预处理一下即可

==我搞那个b=qpow(10ll,n,(ll)prim[i]*9)要模\(prim[i]*9\)推了好久

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=500000+10,M=5e6+50,inf=0x3f3f3f3f;
int n,sum;char a[N];

int v[M],prim[N],cnt=0;
void Prime(int m){
    for(int i=2;i<=m;i++){
        if(!v[i]) v[i]=i,prim[++cnt]=i;
        for(int j=1;j<=cnt&&prim[j]<=m/i;j++){
            v[i*prim[j]]=prim[j];
            if(!i%prim[j]) break; 
        }
    }
}

ll qpow(ll a,int b,ll P){
    ll ret=1ll;
    while(b){
        if(b&1) ret=(ret*a)%P;
        a=(a*a)%P,b>>=1;
    }
    return ret;
}

int main(){
    //freopen("candy.in","r",stdin);
//  freopen("candy.out","w",stdout);
    Prime(4500000);
    //printf("%d\n",cnt);
    //printf("%d %d",v[11111],v[111111]);
    while(scanf("%s",a+1)!=EOF){
        n=strlen(a+1),sum=0;
        for(int i=1;i<=n;++i) sum+=(a[i]-'0');
        int ans=v[sum];
        ll b;
        for(int i=1;i<=cnt&&prim[i]<(sum==1?inf:ans);++i){
            b=qpow(10ll,n,(ll)prim[i]*9);//
            b=(b-1)/9;
            if(!b%prim[i]){ans=prim[i];break;}
        }
        printf("%d\n",ans);
    }
    return 0;
}

遗失的二叉树

小T很喜欢研究树形数据结构,这一天,他的哥哥小Q丢给了小T一个问题:给定一序列,判断其是否为一颗二叉树的中序遍历,对于小T来说,这个问题太简单了,所以哥哥又添加了一个条件:树边连接的两个点的权值不能互质。现在小T对这个问题毫无对策,于是他请你帮他解决这个问题。

Tree’s Solution
考虑区间\(dp\),\(L[l][r]\)表示区间\([l,r]\) 是否可以作为r的左儿子,即\(L[l][r]\)表示以r为根 [l,r-1]为左子树是否合法,\(R[l][r]\)表示区间\([l,r]\)是否可以作为l的右儿子,即\(R[l][r]\)表示以\(l\)为根\([l+1,r]\)为右子树是否合法, 枚举\(k\)与根节点进行转移,那么就可以得到方程:
\(L[l][r] |= L[l][k]\& R[k][r-1]\&mp[k][r]\);
\(R[l][r] |= L[l+1][k]\&R[k][r]\&mp[k][l];\)
最后判断一下存不存在一个\(i\)使得\((L[1][i]\&R[i][n])==1\)即可

==看到中序遍历然后就放弃 刚另外两道题用了太多时间 最后这题只剩差不多半个小时四十分钟的亚子

#include<bits/stdc++.h>
using namespace std;
const int N=500+10,M=1e5+50,inf=0x3f3f3f3f;
int n,ok,a[N],b[N][N],L[N][N],R[N][N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
int main(){
    freopen("T1.txt","r",stdin);
    //freopen("and.out","w",stdout);
    int T;rd(T);
    while(T--){
        rd(n);ok=0;
        memset(b,0,sizeof(b));
        memset(L,0,sizeof(L));
        memset(R,0,sizeof(R));
        for(int i=1;i<=n;++i) rd(a[i]),L[i][i]=R[i][i]=b[i][i]=1;
        for(int i=1;i<=n;++i)
        for(int j=i+1;j<=n;++j) b[i][j]=b[j][i]=(gcd(a[i],a[j])!=1);
        for(int len=2;len<=n;++len)
        for(int i=1,j;(j=i+len-1)<=n;++i)
        for(int k=i;k<=j&&(!L[i][j]||!R[i][j]);++k)
        L[i][j]|=(L[i][k]&R[k][j-1]&b[k][j]),
        R[i][j]|=(L[i+1][k]&R[k][j]&b[k][i]);
        for(int i=1;i<=n&&!ok;++i) if(L[1][i]&R[i][n]) ok=1;
        if(ok) puts("Yes");
        else puts("No");
    }
    return 0;
}

精灵

wonderland的地图可以抽象成一个N个点的有根树,第i个点上生活着编号为i的精灵,根节点为1号节点。

一个点的深度定义为这个节点到根的距离+1,第i只精灵和第j只精灵的亲密度为他们在树上最近公共祖先的深度。

现在Jessica想询问你Q次,每次询问第z只精灵和第l~r只精灵的亲密度的和是多少。答案对201314(不是一个质数)取模。

看完题 1591261-20190915154056519-1490575144.png 75分很稳3hF8OSTmf7aYABJ.jpg

然后想好了暴力的思路 准备去看第二题 看着中序遍历我还是滚了...

在草稿本上捯饬了半天 我居然想出了正解

对不起我询问开的一倍空间我这就滚 30

100昏

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls (o<<1)
#define rs (o<<1|1)
const int N=1e5+10,M=1e5+50,inf=0x3f3f3f3f,P=201314;
int n,m;ll ans[N];
struct quer{
    int id,pos,k,x;
    bool operator <(const quer&X)const{return pos<X.pos;}
}q[N<<1];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,nxt;}e[N];
void add(int u,int v){
    e[++tot]=(edge){v,head[u]},head[u]=tot; 
}

int idx=0,dfn[N],f[N],son[N],sz[N],dep[N],top[N];
void dfs1(int u,int fa){
    dep[u]=dep[fa]+1,sz[u]=1;
    for(int i=head[u],v,mxs=-1;i;i=e[i].nxt){
        dfs1((v=e[i].v),u),sz[u]+=sz[v];
        if(sz[v]>mxs) son[u]=v,mxs=sz[v]; 
    }
}
void dfs2(int u,int topf){
    dfn[u]=++idx,top[u]=topf;
    if(!son[u]) return;
    dfs2(son[u],topf);
    for(int i=head[u],v;i;i=e[i].nxt)
    if((v=e[i].v)!=son[u]) dfs2(v,v);
}

struct node{ll val,tg;}t[N<<2];
void pup(int o){t[o].val=t[ls].val+t[rs].val;}
void updnode(int o,int l,int r,ll k){t[o].val+=(r-l+1)*k,t[o].tg+=k;}
void pudw(int o,int l,int r){
    if(!t[o].tg) return;
    int mid=l+r>>1;
    updnode(ls,l,mid,t[o].tg),updnode(rs,mid+1,r,t[o].tg),t[o].tg=0;
}
void upd(int o,int l,int r,int x,int y,ll k){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){updnode(o,l,r,k);return;}
    pudw(o,l,r);
    int mid=l+r>>1;
    upd(ls,l,mid,x,y,k),upd(rs,mid+1,r,x,y,k);
    pup(o);
}
ll query(int o,int l,int r,int x,int y){
    if(l>y||r<x) return 0;
    if(x<=l&&r<=y) return t[o].val;
    pudw(o,l,r);
    int mid=l+r>>1;ll ans;
    ans=query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y);
    pup(o);
    return ans;
}

void updrange(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        upd(1,1,n,dfn[top[x]],dfn[x],1);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    upd(1,1,n,dep[x],dep[y],1);
}
ll qrange(int x,int y){
    ll sum=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        sum+=query(1,1,n,dfn[top[x]],dfn[x]);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    sum+=query(1,1,n,dep[x],dep[y]);
    return sum;
}

int main(){
    freopen("T1.txt","r",stdin);
//  freopen("elf.out","w",stdout);
    rd(n),rd(m);
    for(int i=2,x;i<=n;++i) rd(f[i]),add(++f[i],i);
    dfs1(1,0),dfs2(1,1);
    int x,l,r,C=0;
    for(int i=1;i<=m;++i){
        rd(l),rd(r),rd(x);
        q[++C]=(quer){i,++l-1,-1,++x},q[++C]=(quer){i,++r,1,x};
    }
    sort(q+1,q+C+1);
    for(int i=1,j=0,pos,id;i<=C;++i){
        id=q[i].id,pos=q[i].pos,x=q[i].x;
        while(j<n&&j<pos) updrange(1,++j);
        ans[id]=(ans[id]+q[i].k*qrange(1,x))%P;
    }
    for(int i=1;i<=m;++i) printf("%lld\n",((ll)ans[i]+P)%(1ll*P));
    return 0;
}

转载于:https://www.cnblogs.com/lxyyyy/p/11523001.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值