• 2017-10-4 清北刷题冲刺班p.m


    P102
    zhx


    a


    【问题描述】
    你是能看到第一题的 friends 呢。
    ——hja
    两种操作:
    1、加入一个数。
    2、询问有多少个数是?的倍数。
    【输入格式】
    第一行一个整数?,代表操作数量。
    接下来?行,每行两个数???,?。其中???表示是哪种操作,第二个?是操作的
    参数。
    【输出格式】
    一行一个整数,代表所有询问答案的异或值。
    【样例输入】
    5
    1 2
    1 3
    2 2
    1 6
    2 3
    【样例输出】
    3
    【数据范围与规定】
    对于第?组数据,? ≤ ? = 1000?。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define maxn 400010
    using namespace std;
    int n,opt,x,sum[maxn];
    long long ans=0;
    int main(){
        //freopen("a.in","r",stdin);
        freopen("a.in","r",stdin);freopen("a.out","w",stdout);
        scanf("%d",&n);
        while(n--){
            scanf("%d%d",&opt,&x);
            if(opt==1){//插入一个数 
                int i;
                for(i=1;i*i<x;i++){
                    if(x%i==0){
                        sum[i]++;
                        sum[x/i]++;
                    }
                }
                int w=sqrt(x);
                if(w*w==x)sum[w]++;
            }
            if(opt==2)
                ans=ans^sum[x];
        }
        cout<<ans;
        fclose(stdin);fclose(stdout);
        return 0;
    }
    100分

    b


    【问题描述】
    你是能看到第二题的 friends 呢。
    ——laekov
    Hja 有一棵?个点的树,树上每个点有点权,每条边有颜色。一条路径的权
    值是这条路径上所有点的点权和,一条合法的路径需要满足该路径上任意相邻
    的两条边颜色都不相同。问这棵树上所有合法路径的权值和是多少。
    【输入格式】
    第一行一个数?。
    一行?个数代表每个点的权值。
    接下来? − 1行每行三个整数?,?,?,代表?到?之间有一条颜色为?的边。
    【输出格式】
    一行一个整数代表答案。
    【样例输入】
    6
    6 2 3 7 1 4
    1 2 1
    1 3 2
    1 4 3
    2 5 1
    2 6 2
    【样例输出】
    134
    【数据范围与规定】
    30%的数据,1 ≤ ? ≤ 1000。
    数据随机 另外20%的数据,是一条链。
    对于100%的数据,1 ≤ ? ≤ 3 × 10 5 ,1 ≤ ? ≤ 10 9 。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define maxn 300010
    int n,w[maxn],num,head[maxn],s[maxn],col[maxn],nu[maxn];
    bool vis[maxn];
    long long ans;
    struct node{
        int to,pre,v;
    }e[maxn*2];
    void Insert(int from,int to,int v){
        e[++num].to=to;
        e[num].v=v;
        e[num].pre=head[from];
        head[from]=num;
    }
    bool flag;
    void dfs(int now,int father,int sum){
        flag=0;ans+=sum;
        for(int i=head[now];i;i=e[i].pre){
            int to=e[i].to;
            if(e[i].v==father)continue;
            flag=1;
            dfs(to,e[i].v,sum+w[to]);
        }
    }
    int du[maxn];
    int main(){
        //freopen("Cola.txt","r",stdin);
        freopen("b.in","r",stdin);freopen("b.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        int x,y,z;
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&x,&y,&z);
            Insert(x,y,z);Insert(y,x,z);
            du[x]++;du[y]++;
        }
        bool fl=1;
        int st;
        for(int i=1;i<=n;i++){
            if(du[i]==1)st=i;
            if(du[i]>2){
                fl=0;
                break;
            }
        }
        if(fl){//是一条链 
            int cnt=0;
            s[1]=w[st];
            vis[st]=1;
            while(1){
                for(int i=head[st];i;i=e[i].pre){
                    if(vis[e[i].to])continue;
                    vis[e[i].to]=1;
                    cnt=cnt+1;
                    col[cnt]=e[i].v;
                    st=e[i].to;
                }
                s[cnt+1]=s[cnt]+w[st];
                if(du[st]==1)break;
            }
            s[cnt+1]=s[cnt]+w[st];
            nu[1]=0;nu[2]=1;
            for(int i=2;i<=cnt;i++){
                if(col[i]!=col[i-1]){
                    nu[i+1]=nu[i]+1;
                }
                else nu[i+1]=1;
            }
            for(int i=2;i<=cnt+1;i++){
                for(int j=1;j<=nu[i];j++){
                    ans+=s[i]-s[i-j-1];
                }
            }
            cout<<ans;
            return 0;
        }
        for(int i=1;i<=n;i++){
            flag=0;
            dfs(i,0,w[i]);
            if(!flag)ans-=w[i];
        }
        ans/=2;
        cout<<ans;
        fclose(stdin);fclose(stdout);
        return 0;
    }
    50分 爆搜+链的特判
    #define ll long long
    #include<iostream>
    #define N 300005
    #include<cstdio>
    #define M 2*N
    using namespace std;
    int n,a[N],head[N],to[M],Next[M],e,col[M];
    ll g[N],nu[N];
    ll ans;
    void buid(int u,int v,int c){
        Next[++e]=head[u];head[u]=e;
        to[e]=v,col[e]=c;
    }
    void dfs(int now,int f,int cf){
        ll G=0;
        g[now]=a[now];nu[now]=1;
        int fl=1;
        for(int i=head[now];i;i=Next[i]){
            int j=to[i];if(j==f) continue;
            dfs(j,now,col[i]);
            if(col[i]!=cf){
                fl=0;
                nu[now]+=nu[j];
                g[now]+=nu[j]*a[now]+g[j];
            }
            G+=nu[j]*a[now]+g[j]; 
        }
        ans+=G;
        if(fl)return;
        for(int i=head[now];i;i=Next[i]){
            int j=to[i];
            if(j==f) continue;
            for(int I=i;I;I=Next[I]){
                int J=to[I];
                if(J==f) continue;
                if(col[i]!=col[I])
                    ans+=g[j]*nu[J]+g[J]*nu[j]+a[now]*nu[j]*nu[J];
            }
        }
    }
    int main(){
        freopen("b.in","r",stdin);
        freopen("b.out","w",stdout);
        
        scanf("%d",&n); 
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<n;++i){
            int u,v,c;scanf("%d%d%d",&u,&v,&c);
            buid(u,v,c);
            buid(v,u,c);
        }
        dfs(1,0,0);
        cout<<ans<<endl;
        return 0;
    }
    100分 树形dp

    c


    【问题描述】
    你是能看到第三题的 friends 呢。
    ——aoao
    Hja 特别有钱,他买了一个? × ?的棋盘,然后 Yjq 到这个棋盘来搞事。一
    开始所有格子都是白的,Yjq 进行?次行操作?次列操作,所谓一次操作,是将对
    应的行列上的所有格子颜色取反。 现在 Yjq 希望搞事之后棋盘上有?个黑色格子,
    问 Yjq 有多少种搞事的方法。
    【输入格式】
    第一行五个整数?,?,?,?,?。
    【输出格式】
    一行一个整数代表答案对10 9 + 7取模之后的值。
    【样例输入】
    2 2 2 2 4
    【样例输出】
    4
    【数据规模与约定】
    对于100%的数据,1 ≤ ?,?,?,? ≤ 100000,0 ≤ ? ≤ ? × ?,有部分分。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #ifdef WIN32
    #define LL "%I64d"
    #else
    #define LL "%lld"
    #endif
    using namespace std;
    #define maxn 100010
    #define mod 1000000007
    int n,m,r,c,ans;
    int v0[maxn],v1[maxn],v2[maxn],v3[maxn],v4[maxn];
    long long s;
    int mul(long long a,int b){
        a*=b;
        if (a>=mod) a%=mod;
        return (int)a;
    }
    int Pow(int a,int b){
        int res=1;
        while(b){
            if(b&1)res=mul(res,a);
            a=mul(a,a);
            b>>=1;
        }
        return res;
    }
    void inc(int &a,int b){
        a+=b;
        if(a>=mod)a-=mod;
    }
    int main(){
        freopen("c.in","r",stdin);freopen("c.out","w",stdout);
        scanf("%d%d%d%d"LL,&n,&m,&r,&c,&s);
        v1[0]=1;
        for(int i=1;i<=100000;i++)v0[i]=Pow(i,mod-2);    // v0[i] 存放的是 i 的逆元
        int tmp=1;
        for(int i=0;i<=(r>>1);i++){                        // v1[i] 即C(n+i-1, i)
            v1[i]=tmp;
            tmp=mul(tmp,mul(i+n,v0[i+1]));
        }
        tmp=1;
        for(int i=0;i<=(c>>1);i++){                        // v2[i] 即C(m+i-1, i)
            v2[i]=tmp;
            tmp=mul(tmp,mul(i+m,v0[i+1]));
        }
        tmp=1;
        for(int i=0;i<=n;i++){                            // v3[i] 即C(n, i)
            v3[i]=tmp;
            tmp=mul(tmp,mul(n-i,v0[i+1]));
        }
        tmp=1;
        for(int i=0;i<=m;i++){                            // v4[i] 即C(m, i)
            v4[i]=tmp;
            tmp=mul(tmp,mul(m-i,v0[i+1]));
        }
        for(int i=r&1;i<=min(n,r);i+=2){                //枚举.....(r-6), (r-4), (r-2), r
            if(i*2!=n){
                if(((s-(long long)i*m))%(n-i*2))continue;    // s = r0*m+c0*n-2*r0*c0 ==> (s-r0*m) = c0*(n-r0*2)
                int b=(int)((s-(long long)i*m)/(n-i*2));    // 计算 c0
                if(b>c||b<0||((c-b)&1))continue;            // 判断这个c0是否可能
                int nowans=v3[i];
                nowans=mul(nowans,v1[(r-i)>>1]);
                nowans=mul(nowans,v4[b]);
                nowans=mul(nowans,v2[(c-b)>>1]);
                //答案就是首先在n行里面选r0行,在m列里面选c0的方案数,再乘上选(r-r0)/2个行的方案数(这些行被操作两次,相当于没有动),再乘上选(c-c0)/2个列的方案数
                inc(ans,nowans);
            }
            else{        //在这种条件下呢,无论列数怎么变,黑色格子数量都不会变了,恒定为r0*m,(这个时候等式(s-r0*m) = c0*(n-r0*2)中n-r0*2为0,c0的值不唯一)
                if((long long)i*m!=s)continue;
                int nowans=v3[i];
                nowans=mul(nowans,v1[(r-i)>>1]);        //这部分同上
                int cnt=0;
                for(int b=(c&1);b<=min(r,c);b+=2)        //因为列的数量不影响答案所以要枚举所有可能的列数分别计算一遍
                    inc(cnt,mul(v4[b],v2[(c-b)>>1]));
                inc(ans,mul(nowans,cnt));    //    这里应该是mul(nowans, cnt)吧?
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    100分
  • 相关阅读:
    复制过来的东西也不靠谱,微信公众号第三方平台的API
    微信的加解密
    郁闷的错误
    Jquery Table 操作
    Html获取经纬度
    Mvc5 Html.EditorFor
    MVC5 烂笔头
    第三方应用开发的一点心得
    Socket 简易静态服务器 WPF MVVM模式(三)
    Socket 简易静态服务器 WPF MVVM模式(二)
  • 原文地址:https://www.cnblogs.com/thmyl/p/7625959.html
Copyright © 2020-2023  润新知