zoukankan      html  css  js  c++  java
  • 2017 ACM-ICPC, Universidad Nacional de Colombia Programming Contest gym101466 题解

    A. 给你n个不超过1e18的数字,n的数量级是1e6。从中选出两个数,做无进位加法,问最大的数能多大。

      sol:将每个数字补成相同长度,除了第一个数字外,每一个数只需要在字典树上贪心的去跑就行了。查询完之后,将这个数字插入到字典树中。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline LL read(){
        LL res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 20'000'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    int T[MAXN][10], tol;
    
    LL pw[25];
    
    void Insert(LL x){
        vector<int> arr;
        while(SZ(arr)<20){
            arr.push_back(x%10);
            x/=10;
        }
        reverse(all(arr));
    
        int now=0;
        for(int i=0;i<20;++i){
            if(!T[now][arr[i]])T[now][arr[i]]=++tol;
            now=T[now][arr[i]];
        }
    }
    
    LL queryMin(LL x){
        LL res=0;
        vector<LL> arr;
    
        while(SZ(arr)<20){
            arr.push_back(x%10);
            x/=10;
        }
    
        reverse(all(arr));
    
        int now=0;
        for(int i=0;i<20;++i){
            LL nd=0;
            LL mn=11;
            for(int j=0;j<10;++j){
                if(T[now][j]){
                    if((arr[i]+j)%10<mn){
                        mn=(arr[i]+j)%10;
                        nd=T[now][j];
                    }
                }
            }
    
            res+=mn*pw[19-i];
            now=nd;
        }
        return res;
    }
    
    LL queryMax(LL x){
        LL res=0;
        vector<LL> arr;
    
        while(SZ(arr)<20){
            arr.push_back(x%10);
            x/=10;
        }
    
        reverse(all(arr));
    
        int now=0;
        for(int i=0;i<20;++i){
            LL nd=0;
            LL mx=-1;
            for(int j=0;j<10;++j){
                if(T[now][j]){
                    if((arr[i]+j)%10>mx){
                        mx=(arr[i]+j)%10;
                        nd=T[now][j];
                    }
                }
            }
            res+=mx*pw[19-i];
            now=nd;
        }
    
        return res;
    }
    
    LL n;
    
    int main(){
        pw[0]=1;
        for(int i=1;i<=18;++i)pw[i]=pw[i-1]*10ll;
    
        n=read();
        LL ans1=(LL)1e19, ans2=0;//最大值不够大wa
        for(int i=1;i<=n;++i){
            LL x=read();
            if(i>1){
                ans1=min(ans1,queryMin(x));
                ans2=max(ans2,queryMax(x));
            }
            Insert(x);
        }
    
        cout<<ans1<<" "<<ans2<<endl;
        return 0;
    }
    
    /*
    2
    1000000000000000000 1000000000000000000
    */
    View Code

    B. 给你n个数字,表示你可以选择一个深度,这个深度每一个节点的儿子节点个数为这n个数中的一个,问最多能有多少个节点。

      sol:显然从大到小排序,算一下个数就行了。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline LL read(){
        LL res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    
    LL n;
    LL A[50];
    
    int main(){
        n=read();
        for(int i=1;i<=n;++i)A[i]=read();
        sort(A+1,A+1+n);
    
        LL ans=1;
        LL t=1;
        for(int i=n;i>=1;--i){
            ans+=t*A[i];
            t*=A[i];
        }
    
        cout<<ans;
    
        return 0;
    }
    View Code

    C. 给定三维空间n个点,第一个点为中心点,要将中心点与其他点连线,形成一条一条直线。使得除中心点以外的其他点至少被一条直线覆盖。最少需要连多少条直线?

      sol:从第二个点开始,与中心点连线。并且将其他共线的点打上标记,判断共线就用点积就行。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 5'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    
    struct Node{
        LL x, y, z;
        Node(){}
        Node(LL _x, LL _y, LL _z){
            x=_x;y=_y;z=_z;
        }
        Node operator-(const Node& a){
            return Node(x-a.x,y-a.y,z-a.z);
        }
    }points[MAXN];
    
    LL n;
    
    int vis[MAXN];
    
    LL Dot(Node a, Node b){
        return a.x*b.x+a.y*b.y+a.z*b.z;
    }
    
    int main(){
        n=read();
        for(int i=1;i<=n;++i){
            points[i].x=read();
            points[i].y=read();
            points[i].z=read();
        }
    
        int ans=0;
    
        for(int i=2;i<=n;++i){
            if(vis[i])continue;
            else{
                ++ans;
                for(int j=i+1;j<=n;++j){
                    LL t=Dot(points[i]-points[1],points[j]-points[1]);
                    if(t*t==Dot(points[i]-points[1],points[i]-points[1])*Dot(points[j]-points[1],points[j]-points[1])){
                        vis[j]=1;
                    }
                }
            }
        }
    
        cout<<ans<<endl;
        return 0;
    }
    View Code

    D. 初始时,你有一个数,值为0,你可以进行两种操作。第一种:将这个值变成2*x+1,第二种,将这个值变成2*x+2。问经过多少次操作可以将0变成一个指定的值。

      sol:由于两种操作出来的值奇偶性不同,注意到这个,就可以进行逆推了。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    
    int n;
    
    int main(){
        n=read();
    
        string ans;
        while(n){
            if(n&1){
                ans+="A";
                --n;
                n/=2;
            }else{
                ans+="B";
                n-=2;
                n/=2;
            }
        }
    
        reverse(all(ans));
        cout<<ans;
        return 0;
    }
    View Code

    E. 给一个文本串,和一个模式串和一个整数k。问这个模式串在文本串中出现的次数>=k的最长前缀。

      sol:先跑kmp的前置,得到fail指针。然后开始跑匹配的时候,可以搞出每一个文本串前缀,所匹配模式串的最大前缀,而每一个模式串的前缀,对其fail指针指向的模式串前缀是有贡献的(之所以不是所有前缀是因为,这样搞会算重)。我们跑完之后,倒着扫一遍我们的计数数组,当个数大于等于k的时候,得到答案,否则给其对应fail指针的位置加上贡献。

      sol2:注意到单调性,就可以二分答案,逐个check。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    char s[MAXN];
    
    char pat[MAXN];
    
    int Next[MAXN];
    
    int cnt[MAXN];
    
    void getNext(char* str){
        int len=strlen(str+1);
        Next[1]=0;
        int j=0;
    
        for(int i=2;i<=len;++i){
            while(j&&str[i]!=str[j+1])j=Next[j];
            if(str[i]==str[j+1])++j;
            Next[i]=j;
        }
    }
    
    void Match(char* s1, char* s2){
        getNext(s2);
        int len1=strlen(s1+1);
        int len2=strlen(s2+1);
        int j=0;
        for(int i=1;i<=len1;++i){
            while(j&&s1[i]!=s2[j+1])j=Next[j];
            if(s1[i]==s2[j+1])++j;
            ++cnt[j];
    //        cout<<j<<endl;
            if(j==len2)j=Next[j];
        }
    }
    
    int k;
    
    int main(){
        gets(s+1);
        gets(pat+1);
        k=read();
    
        int len1=strlen(s+1);
        int len2=strlen(pat+1);
    
        Match(s, pat);
        int ans=-1;
        for(int i=len2;i>=1;--i){
            if(cnt[i]>=k){
                ans=i;
                break;
            }else{
                cnt[Next[i]]+=cnt[i];
            }
        }
        if(ans==-1)cout<<"IMPOSSIBLE";
        else{
            for(int i=1;i<=ans;++i)cout<<pat[i];
        }
    
        return 0;
    }
    View Code

    F. 判一下给的三个数能不能构成三角形。

      sol:两边之和大于第三边。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    
    int n;
    
    int main(){
        n=read();
        int flag=1;
        for(int i=1;i<=n;++i){
            vector<int> t(3);
            for(int j=0;j<3;++j)t[j]=read();
            sort(all(t));
            if(t[0]+t[1]<=t[2])flag=0;
        }
    
        if(flag)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    
        return 0;
    }
    View Code

    G. 给你一些正整数(2<=x<=1e6),首先你要将这些数质因数分解。并且将这个质因数拼接成一个字符串,现在允许两种操作,第一是从这个字符串中取出一个数字(1<=num<=9),换成一个字母(a=1,b=2,...)。拼到一个目标字符串的后面。第二是取出两个数字,拼成一个数字。这个数字显然在(10<=num<=26)之间,同样是换成对应的字母。拼接到目标字符串的后面。问我们最终能拼成的目标字符串的种类数。

      sol:首先我们有一个观察,由于x<=1e6,所以在质因数分解的过程中,拼成的字符串长度<=20。为什么这么说呢?我们考虑质因数2,长度占1,如果全是2,1e6也最多20个。对于其他的长度占1的质因数而言,贡献来的大,代价却不变,显然不会超过20个。考虑其他两位数,三位数的质因数呢?由于两个数的质因数,代价是2,贡献大于4,不会超过20位,其他同理。那么既然第一个字符串长度不超过20,这个题就变得极容易了,直接考虑状压dp,记忆化搜索就能通过了。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    int dp[(1<<20)+5];
    
    vector<int> a;
    
    int sz;
    
    int dfs(int state){
        if(dp[state]!=-1)return dp[state];
    
        if(state==0) return 1;
    
        int& ret=dp[state];
        ret=0;
    
        int vis[27]={};
    
        for(int i=0;i<sz;++i){
            if((state&(1<<i))&&a[i]!=0){
                if(!vis[a[i]]){
                    vis[a[i]]=1;
                    addmod(ret,dfs(state^(1<<i)));
                }
    
                for(int j=0;j<sz;++j){
                    if(i!=j&&(state&(1<<j))){
                        int x=a[i]*10+a[j];
                        if(x>=10&&x<=26&&!vis[x]){
                            vis[x]=1;
                            addmod(ret,dfs(state^(1<<i)^(1<<j)));
                        }
                    }
                }
            }
        }
    
        return ret;
    }
    
    int main(){
        int n;
        while(cin>>n){
            memset(dp,-1,sizeof dp);
            a.clear();
            int nn=n;
            for(int i=2;i*i<=nn;++i){
                while(n%i==0){
                    int ii=i;
                    while(ii>0){
                        a.PB(ii%10);
                        ii/=10;
                    }
                    n/=i;
                }
            }
    
            if(n>2){
                while(n>0){
                    a.PB(n%10);
                    n/=10;
                }
            }
    
            sz=SZ(a);
    
            cout<<dfs((1<<sz)-1)<<endl;
        }
    
        return 0;
    }
    View Code

    H. C语言期末考试题(逃。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    int m;
    
    int main(){
        m=read();
        for(int i=1;i<=m;++i){
            if(i==1){
                cout<<"*";
                for(int j=1;j<=m-2;++j)cout<<" ";
                cout<<"* ";
                for(int j=1;j<=m;++j)cout<<"*";
                cout<<endl;
            }else if(i==m){
                for(int j=1;j<=m;++j)cout<<"*";
                cout<<" ";
                cout<<"*";
                for(int j=1;j<=m-2;++j)cout<<" ";
                cout<<"*";
            }else{
                cout<<"*";
                for(int j=1;j<=m-2;++j)cout<<" ";
                cout<<"* ";
                cout<<"*";
                for(int j=1;j<=m-2;++j)cout<<" ";
                cout<<"*";
                cout<<endl;
            }
    
        }
    
        return 0;
    }
    View Code

    I. 给你一个数组,你要将这个数组分成两个组,第一组的数字全都是回文串,第二组的数字里面只有4和7。问你能不能存在一种方法,使得你的分组方式,能够使得每一组的数字在原数组中距离相差不超过20。

      sol:题目还是很直观的,我们显然要设计一个dp状态,dp[cur][x1][x2][s1][s2],表示当前处理到了第cur个,上一个第一组的与前一个的距离,上一个第二组的与前一个的距离,第一组的最后一个数是否有邻居,第二组的最后一个数是否有邻居(两个标志位维度是为了更好处理每组第一个)是否能分组。那么问题就来了,首先是x1,x2,要是直接开1e5,那显然会MLE(建议放到太湖之光上跑)。考虑到距离大于20的都可以认为是21,能减小空间复杂度。但是可惜的是,即使我们把dp[cur][x1][x2][s1][s2]换成bool型还是会MLE。所以我们这个时候换成bitset就可以通过(出题人老毒瘤了)。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 100'010;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    //两组分别看的话,只有这一组里前一个比较重要
    //为了解决第一个的问题,引入了标记
    
    bitset<MAXN> dp[22][22][2][2];
    bitset<MAXN> vis[22][22][2][2];
    
    int mark[MAXN];
    
    int n, k;
    
    bool check1(int x){
        vector<int> arr;
        while(x){
            arr.push_back(x%10);
            x/=10;
        }
        int sz=SZ(arr);
    
        for(int i=0;i<sz/2;++i)
            if(arr[i]!=arr[sz-i-1])return false;
    
        return true;
    }
    
    bool check2(int x){
        while(x){
            if(x%10!=4&&x%10!=7)return false;
            x/=10;
        }
    
        return true;
    }
    
    bool dfs(int cur, int d1,int d2, int isOk1, int isOk2){
        if(vis[d1][d2][isOk1][isOk2][cur])return dp[d1][d2][isOk1][isOk2][cur];
    
        if(cur==n+1){
            if(!isOk1||!isOk2)return 0;
            else return 1;
        }
    
        vis[d1][d2][isOk1][isOk2][cur]=1;
    
        bool ret=0;
    
        if(mark[cur]&1){
            if(d1!=k+1||isOk1){
                ret|=dfs(cur+1,1,min(k+1,d2+1),d1<=k?1:0,isOk2);
            }
        }
    
        if(mark[cur]&2){
            if(d2!=k+1||isOk2){
                ret|=dfs(cur+1,min(k+1,d1+1),1,isOk1,d2<=k?1:0);
            }
        }
    
        return dp[d1][d2][isOk1][isOk2][cur]=ret;
    
    }
    
    int main(){
        n=read();k=read();
        for(int i=1;i<=n;++i){
            int x=read();
            if(check1(x))mark[i]|=1;
            if(check2(x))mark[i]|=2;
            if(mark[i]==0){
                cout<<"NO";
                return 0;
            }
        }
    
        int ok=dfs(1,k+1,k+1,1,1);
        if(ok)cout<<"Yes";
        else cout<<"No";
    
        return 0;
    }
    View Code

    J. 先给你m个数,要组成长度为n的数组。i>m时a[i]=(a[i-m]+a[i-m+1])%mod。问你把这些数升序排列之后,q此询问,每次询问ranki。

      sol:模拟即可。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 30'000'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    
    int cnt[MAXN];
    int n, m, q;
    
    int A[MAXN];
    
    int main(){
        n=read();m=read();q=read();
        for(int i=1;i<=m;++i)A[i]=read(),++cnt[A[i]];
    
        for(int i=m+1;i<=n;++i){
            A[i]=(A[i-m]+A[i-m+1])%30000000;
            ++cnt[A[i]];
        }
    
        for(int i=1;i<=30000000;++i)cnt[i]=cnt[i]+cnt[i-1];
    
        for(int i=1;i<=q;++i){
            int x=read();
            int ans=lower_bound(cnt,cnt+30000000,x)-cnt;
            cout<<ans<<endl;
        }
    
        return 0;
    }
    View Code

    K. 给你一颗树,有n个点,每一个点有点权。现在给出两种操作,第一是查询一个节点子树的所有点权乘积的因子数。第二个将树上某一个节点的值乘上val。题目保证所有数的最大素因子不超过13。

      sol:子树问题当然要dfs序,考虑到最大素因子不超过13,写6颗线段树就能通过了,代码量稍大,但也是送分题。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200'005;
    
    const int MOD = 1000000007;
    
    void addmod(int& a, int b){a+=b;if(a>=MOD)a-=MOD;}
    int mulmod(int a, int b){return 1ll*a*b%MOD;}
    
    template<typename T>
    void chmin(T a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T a, T b){if(b>a)a=b;}
    
    #define go(e,u) for(int e=head[u];e;e=Next[e])
    int to[MAXN<<1],Next[MAXN<<1],head[MAXN],tol;
    
    void add_edge(int u,int v){
        Next[++tol]=head[u];to[tol]=v;head[u]=tol;
        Next[++tol]=head[v];to[tol]=u;head[v]=tol;
    }
    
    int arr[]={2,3,5,7,11,13};
    
    inline int getid(int x){return lower_bound(arr,arr+7,x)-arr;}
    
    int n;
    
    int L[MAXN], R[MAXN], dfn, id[MAXN];
    
    int P[MAXN<<2];
    
    int T[MAXN<<2][6];
    
    int val[MAXN];
    
    void dfs(int u,int f){
        L[u]=++dfn;
        id[dfn]=u;
    
        go(e,u){
            int v=to[e];
            if(v==f)continue;
            dfs(v,u);
        }
    
        R[u]=dfn;
    }
    
    
    void build1(int nd, int l, int r){
        if(l==r){
            P[nd]=val[id[l]];
            return;
        }
    
        build1(lson, l, mid);
        build1(rson, mid+1, r);
    
        P[nd]=1ll*P[lson]*P[rson]%MOD;
    }
    
    void update1(int nd, int l, int r, int pos, int v){
        if(l==r){
            P[nd]=1ll*P[nd]*v%MOD;
            return;
        }
    
        if(pos<=mid)update1(lson, l, mid, pos, v);
        else update1(rson, mid+1, r, pos, v);
    
        P[nd]=1ll*P[lson]*P[rson]%MOD;
    }
    
    int query1(int nd, int l, int r, int L, int R){
        if(L<=l&&r<=R){
            return P[nd];
        }
    
        int res=1;
        if(L<=mid)res=1ll*res*query1(lson, l, mid, L, R)%MOD;
        if(R>=mid+1)res=1ll*res*query1(rson, mid+1, r, L, R)%MOD;
    
        return res;
    }
    
    void build2(int nd, int l, int r){
        if(l==r){
            int x=val[id[l]];
            for(int i=0;i<6;++i){
                int num=0;
                while(x%arr[i]==0){
                    ++num;
                    x/=arr[i];
                }
                T[nd][i]+=num;
            }
            return;
        }
    
        build2(lson,l,mid);
        build2(rson,mid+1,r);
    
        for(int i=0;i<6;++i)T[nd][i]=T[lson][i]+T[rson][i];
    }
    
    void update2(int nd, int l, int r, int pos, int v){
        if(l==r){
            int x=v;
            for(int i=0;i<6;++i){
                int num=0;
                while(x%arr[i]==0){
                    ++num;
                    x/=arr[i];
                }
                T[nd][i]+=num;
            }
            return;
        }
    
        if(pos<=mid)update2(lson,l,mid,pos,v);
        else update2(rson,mid+1,r,pos,v);
    
        for(int i=0;i<6;++i)T[nd][i]=T[lson][i]+T[rson][i];
    }
    
    vector<int> query2(int nd, int l, int r, int L, int R){
        if(L<=l&&r<=R){
            vector<int> res(6,0);
            for(int i=0;i<6;++i)res[i]=T[nd][i];
            return res;
        }
    
        vector<int> res(6,0);
        if(L<=mid){
            vector<int> t;
            t=query2(lson,l,mid,L,R);
            for(int i=0;i<6;++i)res[i]+=t[i];
        }
    
        if(mid+1<=R){
            vector<int>t;
            t=query2(rson,mid+1,r,L,R);
            for(int i=0;i<6;++i)res[i]+=t[i];
        }
    
        return res;
    }
    
    int main(){
        n=read();
        for(int i=1;i<n;++i){
            int u, v;
            u=read();v=read();
            ++u,++v;
            add_edge(u,v);
        }
        dfs(1,0);
    
        for(int i=1;i<=n;++i)val[i]=read();
        build1(1,1,n);
        build2(1,1,n);
    
        int q;
        q=read();
        while(q--){
            char buf[10];
            scanf("%s",buf+1);
            if(buf[1]=='R'){
                int w=read();
                ++w;
                int lb=L[w],rb=R[w];
                int ans=query1(1,1,n,lb,rb);
                vector<int> res=query2(1,1,n,lb,rb);
                cout<<ans<<" ";
                ans=1;
                for(int i=0;i<6;++i)ans=1ll*ans*(1+res[i])%MOD;
                cout<<ans<<endl;
            }else{
                int p=read();
                ++p;
                p=L[p];
                int v=read();
                update1(1,1,n,p,v);
                update2(1,1,n,p,v);
            }
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    css 样式库
    css命名规则
    css选择器
    清除浏览器自带样式
    导航菜单制作
    清除浮动和样式重置快捷代码
    程序练习网站
    各种布局样式模板
    使用gulp解决外部编辑器修改Eclipse文件延迟刷新
    jQuery Validate 表单验证 — 用户注册简单应用
  • 原文地址:https://www.cnblogs.com/JohnRan/p/12719856.html
Copyright © 2011-2022 走看看