【集训队互测2016】消失的源代码

SOL:

   毒瘤题。做一个两个点还觉得这道题很有意思,但10个点写下来就是心累了。

  point 1:

     对小数据观察发现每个字母唯一确定另一个字母。把26个字母之间的映射关系打表就好了。

#include<bits/stdc++.h>
using namespace std;
char ch[107]="yfrbkgimujvphatdsnelozcxwq";
int T;
char p[1000007];
signed main() {
    freopen("input1.txt","r",stdin);
    freopen("output1.txt","w",stdout);
    scanf("%d",&T);
    scanf("%d",&T);
    while (T--) {
        scanf("%s",p+1); int len=strlen(p+1);
        for (int i=1;i<=len;i++) putchar(ch[p[i]-'a']);
        putchar(10);
    }
}

point 2:

一拿到手,就发现这个函数的增长是O(N^2)的。写了个高消发现系数是2016 4 10 ,但是跑不过样例,所以把1到20全部打出来看了一遍,发现应该是膜了一个数。

#include<bits/stdc++.h>
#define N 205
using namespace std;
const double eps=1e-8;
int n;
double a[N][N],del;
bool gauss(){
    for(int i=1;i<=n;i++){
        int k=i;
        for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[k][i]))k=j;
        if(fabs(del=a[k][i])<eps)return 0;
        for(int j=i;j<=n+1;j++)swap(a[i][j],a[k][j]);
        for(int j=i;j<=n+1;j++)a[i][j]/=del;
        for(k=1;k<=n;k++)if(k!=i){
            del=a[k][i];
            for(int j=i;j<=n+1;j++)a[k][j]-=a[i][j]*del;
        }
    }
    return 1;
}
int T;
long long p;
__int128 x;
#define mo (243990-10657)
void write(__int128 x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(__int128 x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(__int128 x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }

int main(){
    freopen("input2.txt","r",stdin);
    freopen("output2.txt","w",stdout);
    scanf("%d",&T); scanf("%d",&T);
    while (T--) {
        scanf("%lld",&p);
        x=p;
//        printf("%lld\n",);
        writeln((x*x*2016+4*x+10)%mo);
    }
//    cerr<<sqrt(100/pi);
}

point 3:

方法同point 2吧,应该看到出应该是O(N^0.5)这个级别的。算了下系数,发现是根号 π。

#include<bits/stdc++.h>
#define N 205
using namespace std;
const double eps=1e-8;
int n;
double a[N][N],del;
bool gauss(){
    for(int i=1;i<=n;i++){
        int k=i;
        for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>fabs(a[k][i]))k=j;
        if(fabs(del=a[k][i])<eps)return 0;
        for(int j=i;j<=n+1;j++)swap(a[i][j],a[k][j]);
        for(int j=i;j<=n+1;j++)a[i][j]/=del;
        for(k=1;k<=n;k++)if(k!=i){
            del=a[k][i];
            for(int j=i;j<=n+1;j++)a[k][j]-=a[i][j]*del;
        }
    }
    return 1;
}
int T;
long long p;
__int128 x;
#define mo (243990-10657)
void write(__int128 x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(__int128 x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(__int128 x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
#define pi acos(-1)
int main(){
    freopen("input3.txt","r",stdin);
    freopen("output3.txt","w",stdout);
    scanf("%d",&T); scanf("%d",&T);
    while (T--) {
        scanf("%lld",&p);
        printf("%lld\n",(int)sqrt(p/pi));
//        writeln((x*x*2016+4*x+10)%mo);
    }
//    cerr<<sqrt(100/pi);
}

point 4:

怎么说呢,长得像一张图,然后发现完全图的时候  answer=n*n,链的时候也是这样的,但边集为空的时候为n,所以应该能猜出来是sigma 联通图大小的平方。

#include<bits/stdc++.h>
#define N 200007
using namespace std;
long long ans,f[N],siz[N];
int T,n,m,x,y,a,b;
int gf(int x){
    return x==f[x]?x:f[x]=gf(f[x]);
}
signed main () {
//    T=1;
    freopen("input4.txt","r",stdin);
    freopen("output4.txt","w",stdout);
#include<bits/stdc++.h>
#define N 200007
#define SIZ 24
#define eho(x) for(int i=head[x];i;i=net[i])
#define v fall[i]
using namespace std;
long long ans,dep[N],anw;
int T,n,m,x,y,z,f[N][SIZ],a,b,dd[N],fall[N<<1],net[N<<1],tot,head[N],cost[N];
inline void add(int x,int y,int co) {
    fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=co;
}
void dfs(int x,int fa) {
//    cerr<<x<<endl;
    dd[x]=dd[fa]+1;
    f[x][0]=fa; 
    for (int i=1;i<SIZ;i++) 
     f[x][i]=f[f[x][i-1]][i-1];
    eho(x) if (v!=fa) dep[v]=dep[x]+cost[i],dfs(v,x);
}
int pku(int x,int y){
    if (dd[x]<dd[y]) swap(x,y);
    for (int i=SIZ-1;~i;i--) if (dd[f[x][i]]>=dd[y]) x=f[x][i];
    if (x==y) return x;
    for (int i=SIZ-1;~i;i--) 
     if (f[x][i]^f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
signed main () {
//    T=1;
//    freopen("test.txt","r",stdin);
    freopen("input5.txt","r",stdin);
    freopen("output5.txt","w",stdout);
    scanf("%d",&T); scanf("%d",&T);
    while (T--) {
//        memset(f,0,sizeof f);
        memset(head,0,sizeof head); tot=0;
        scanf("%d%d",&n,&m);anw=0;
        for (int i=1;i<n;i++)  {
            scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z);
        }
        dfs(1,0);
        while (m--) {
            scanf("%d%d",&x,&y);
            ans=dep[x]+dep[y]-2*dep[pku(x,y)];
            anw^=ans;
        }
        printf("%lld\n",anw);
    } return 0;
}

 


    scanf("%d",&T); scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n,&m);ans=0;
        for (int i=1;i<=n;i++) f[i]=i,siz[i]=0;
        while (m--) {
            scanf("%d%d",&x,&y);
            a=gf(x); b=gf(y);
            f[a]=b;
        }
        for(int i=1;i<=n;i++) siz[gf(i)]++;
        for(int i=1;i<=n;i++) ans+=1ll*siz[i]*siz[i];
        printf("%lld\n",ans);
    }
}

point 5:先是发现正是一颗树,又发现偶数组询问等于没有询问,所以猜答案是互相xor的。而单组询问是路径两点路径长。

#include<bits/stdc++.h>
#define N 200007
#define SIZ 24
#define eho(x) for(int i=head[x];i;i=net[i])
#define v fall[i]
using namespace std;
long long ans,dep[N],anw;
int T,n,m,x,y,z,f[N][SIZ],a,b,dd[N],fall[N<<1],net[N<<1],tot,head[N],cost[N];
inline void add(int x,int y,int co) {
    fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=co;
}
void dfs(int x,int fa) {
//    cerr<<x<<endl;
    dd[x]=dd[fa]+1;
    f[x][0]=fa; 
    for (int i=1;i<SIZ;i++) 
     f[x][i]=f[f[x][i-1]][i-1];
    eho(x) if (v!=fa) dep[v]=dep[x]+cost[i],dfs(v,x);
}
int pku(int x,int y){
    if (dd[x]<dd[y]) swap(x,y);
    for (int i=SIZ-1;~i;i--) if (dd[f[x][i]]>=dd[y]) x=f[x][i];
    if (x==y) return x;
    for (int i=SIZ-1;~i;i--) 
     if (f[x][i]^f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
signed main () {
//    T=1;
//    freopen("test.txt","r",stdin);
    freopen("input5.txt","r",stdin);
    freopen("output5.txt","w",stdout);
    scanf("%d",&T); scanf("%d",&T);
    while (T--) {
//        memset(f,0,sizeof f);
        memset(head,0,sizeof head); tot=0;
        scanf("%d%d",&n,&m);anw=0;
        for (int i=1;i<n;i++)  {
            scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z);
        }
        dfs(1,0);
        while (m--) {
            scanf("%d%d",&x,&y);
            ans=dep[x]+dep[y]-2*dep[pku(x,y)];
            anw^=ans;
        }
        printf("%lld\n",anw);
    } return 0;
}

point 6:发现输入和point 5一样,不费什么力气就发现了除了单组询问是路径上最短边边权以外和point 5没区别。还有一个坑点就是x==y时的return的不是0,是1987654321

#include<bits/stdc++.h>
#define N 200007
#define SIZ 24
#define int long long 
#define eho(x) for(int i=head[x];i;i=net[i])
#define v fall[i]
using namespace std;
long long ans,dep[N],anw;
int T,n,m,x,y,z,cst[N][SIZ],f[N][SIZ],a,b,dd[N],fall[N<<1],net[N<<1],tot,head[N],cost[N];
inline void add(int x,int y,int co) {
    fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=co;
}
void dfs(int x,int fa) {
//    cerr<<x<<endl;
    dd[x]=dd[fa]+1;
    f[x][0]=fa; 
    for (int i=1;i<SIZ;i++) 
     f[x][i]=f[f[x][i-1]][i-1],cst[x][i]=min(cst[x][i-1],cst[f[x][i-1]][i-1]);
    eho(x) if (v!=fa) cst[v][0]=cost[i],dfs(v,x);
}
int pku(int x,int y){
    if (x==y) return 1987654321;
    int anw=LONG_LONG_MAX;
    if (dd[x]<dd[y]) swap(x,y);
    for (int i=SIZ-1;~i;i--) 
     if (dd[f[x][i]]>=dd[y]) anw=min(anw,cst[x][i]),x=f[x][i];
    if (x==y) return anw;
    for (int i=SIZ-1;~i;i--) 
     if (f[x][i]^f[y][i]) 
      anw=min(anw,cst[x][i]),anw=min(anw,cst[y][i]),x=f[x][i],y=f[y][i];
    return min(anw,min(cst[x][0],cst[y][0]));
}
signed main () {
    T=1;
//    freopen("test.txt","r",stdin);
    freopen("input6.txt","r",stdin);
    freopen("output6.txt","w",stdout);
    scanf("%lld",&T); scanf("%lld",&T);
    while (T--) {
//        memset(f,0,sizeof f);
        memset(head,0,sizeof head); tot=0;
        scanf("%lld",&n);
        cin>>m;
        anw=0;
        for (int i=1;i<n;i++)  {
            scanf("%lld%lld%lld",&x,&y,&z); 
//            cin >>x>>y>>z;
            add(x,y,z); add(y,x,z);
//            cerr<<z<<endl;
        }
        dfs(1,0);
        int xx;
        while (m--) {
            scanf("%lld%lld",&x,&y);
//            cerr<<x<<' '<<y<<' '<<(xx=pku(x,y))<<endl;
            anw^=pku(x,y);
        }
        printf("%lld\n",anw);
    } return 0;
}
//1987654321
//1987654321

point 7:

通过增量法观察发现是gcd的二维前缀和,一个优雅的反演就可以过了。

令f(x,y)为要求的答案,有

f(x,y)* d= D* (x/D)* (y/D)*d

那么就是卷上一个欧拉函数的事情了。

#include<bits/stdc++.h>
using namespace std;
#define N 1000007
int pim[N],tot,t,n,m;
long long mu[N],ans;
void pre(){
    mu[1]=1;
    for (int i=2;i<N;i++) {
        if (!mu[i]) mu[i]=i-1,pim[++tot]=i;
        for (int j=1;j<=tot&&pim[j]*i<N;j++) {
            if (i%pim[j]==0) {
                mu[i*pim[j]]=mu[i]*pim[j]; break;
            }
            mu[i*pim[j]]=mu[i]*(pim[j]-1);
        }
    }
//    for (int i=1;i<100;i++) cout<<mu[i]<<' ';
    for (int i=1;i<N;i++) mu[i]=mu[i-1]+mu[i];
}
signed main () {
    pre();
    freopen("input7.txt","r",stdin);
    freopen("output7.txt","w",stdout);
    scanf("%d%d",&t,&t);
    while (t--) {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);ans=0;
        for (int i=1,last;i<=n;i=last+1) {
            last=min(n/(n/i),m/(m/i));
            ans+=1ll*(n/i)*(m/i)*(mu[last]-mu[i-1]);
        }
        printf("%lld\n",ans);
    } return 0;
}

point 8:观察发现所有的在序列里的值很小,而且答案和序列里具体是哪个值没有关系,只与序列中的其他数是否相等有关,猜一波发现是字符串相关,再想想就知道是求本质不同的字符串。SAM跑一遍就好了。

#include<bits/stdc++.h>
#define SIZ 3000007
using namespace std;
int t,n,x;
long long ans;
struct Node{
    int len,ch[26],fa;
    void clear() {
        fa=len=0; memset(ch,0,sizeof ch);
    }
}T[SIZ];
int q,p,last=1,tot=1,np,c[SIZ],id[SIZ];
long long dp[SIZ],anw;
inline void ext(int x){
    q=++tot; T[q].clear(); 
    T[q].len=T[last].len+1;
    for (;last&&!T[last].ch[x];last=T[last].fa) T[last].ch[x]=q;
    if (!last) T[q].fa=1; else {
        p=T[last].ch[x];
        if (T[last].len+1==T[p].len) T[q].fa=p;
        else {
            np=++tot; T[np]=T[p]; T[np].len=T[last].len+1;
            T[p].fa=T[q].fa=np;
            for (;last&&T[last].ch[x]==p;last=T[last].fa) T[last].ch[x]=np;
        }
    }
    last=q;
}
signed main () {
//    freopen("test.txt","r",stdin);
    freopen("input8.txt","r",stdin);
    freopen("output8.txt","w",stdout);
    scanf("%d%d",&t,&t);
    while (t--) {
        memset(dp,0,sizeof dp);
        memset(c,0,sizeof c);
        memset(id,0,sizeof id);
        memset(T,0,sizeof T);
        last=tot=1; T[1].clear(); T[0].clear();
        scanf("%d",&n);
        cerr<<n<<"rrsb"<<endl;
        for (int i=1;i<=n;i++) {
         scanf("%d",&x);assert(0<=x&&x<26);
         ext(x); }
        for (int i=1;i<=tot;i++) c[T[i].len]++;
        for (int i=1;i<=n;i++) c[i]+=c[i-1];
        for (int i=1;i<=tot;i++) id[c[T[i].len]--]=i;
        dp[1]=1; ans=0;
        for (int i=0;i<26;i++) if(T[1].ch[i]) dp[T[1].ch[i]]+=dp[1];
        for (int i=2;i<=tot;i++) {
            x=id[i];
            for (int j=0;j<26;j++)
             if (T[x].ch[j]) dp[T[x].ch[j]]+=dp[x];
            ans+=dp[x];
        }
        printf("%lld\n",ans);
    } return 0;
}

point 9:求最近点对。玄学暴力复杂度竟然是对的。

#include<bits/stdc++.h>
#define db double
#define N 2000007
#define exp 1e-5
using namespace std;
struct Node{
    int x,y;
    inline bool operator <(const Node&X)const &{
       return x<X.x;
    } 
}a[N];
db ans;
#define Mid (l+r>>1)
inline db que(int x,int y){
    return sqrt(1ll*(a[x].x-a[y].x)*((a[x].x-a[y].x))+1ll*(a[x].y-a[y].y)*(a[x].y-a[y].y));
}
void sol(int l,int r){
    if (r-l<=10) {
        for (int i=l;i<=r;i++)
         for (int j=i+1;j<=r;j++)
          ans=min(ans,que(i,j)); return;
    }
    sol(l,Mid); sol(Mid+1,r);
    for (int i=Mid;(a[Mid].x-a[i].x)<ans+exp&&i>=l;i--)
     for (int j=Mid+1;a[j].x-a[Mid].x<ans+exp&&j<=r;j++)
      ans=min(ans,que(i,j));
}
int t,n;
signed main () {
//    freopen("test.txt","r",stdin);
    freopen("input9.txt","r",stdin);
    freopen("output9.txt","w",stdout);
    scanf("%d%d",&t,&t);
    while (t--) {
        scanf("%d",&n); ans=1e18;
        cerr<<n<<"rrsb\n";
        for (int i=1;i<=n;i++) 
         scanf("%d%d",&a[i].x,&a[i].y);
        sort(a+1,a+n+1);
        sol(1,n);
        printf("%.3lf\n",ans);
    } return 0;
}

point 10:发现怎么输入都是invalid input!

   那么就输出这个。

#include<bits/stdc++.h>
#define db double
#define N 2000007
using namespace std;
struct Node{
    int x,y;
    inline bool operator <(const Node&X)const &{
       return x<X.x;
    } 
}a[N];
db ans;
#define Mid (l+r>>1)
inline db que(int x,int y){
    return sqrt((a[x].x-a[y].x)*((a[x].x-a[y].x))+(a[x].y-a[y].y)*(a[x].y-a[y].y));
}
void sol(int l,int r){
    if (r-l<=10) {
        for (int i=l;i<=r;i++)
         for (int j=i+1;j<=r;j++)
          ans=min(ans,que(i,j)); return;
    }
    sol(l,Mid); sol(Mid+1,r);
    for (int i=Mid;a[Mid].x-a[i].x<ans&&i>=l;i--)
     for (int j=Mid+1;a[j].x-a[Mid].x<ans&&j<=r;j++)
      ans=min(ans,que(i,j));
}
int t,n;
signed main () {
//    freopen("test.txt","r",stdin);
    freopen("input10.txt","r",stdin);
    freopen("output10.txt","w",stdout);
    scanf("%d%d",&t,&t);
    while (t--) {
        printf("invalid input!\n");
    } return 0;
}

讲道理这题目真毒瘤,不是很难,但我写了一天。

posted @ 2018-04-22 20:40  泪寒之雪  阅读(483)  评论(0编辑  收藏  举报