zoukankan      html  css  js  c++  java
  • 2019 USP Try-outs 练习赛

    // 好久没更博客了,最近打了很多场练习赛&校内PK赛,大概自闭忙于补题吧
    // 9.26 周四练习赛

    A. Kolkhozy

    题意

    有 n 个数 (f[i]) ,有 q 次询问(l, r, x, m),求 [l, r] 区间内有多少项满足 (f[i] \%m=x)

    思路

    直接暴力的话复杂度 (O(qcdot n)) ,注意到此题空间给了1024MB,如果能预处理一部分,可以(O(q cdot logn)) 解决。

    对于m比较大的情况,我们发现直接找[l, r]区间内等于 (x + k*m) 的个数即可,那么可以统计每个点值出现的位置,二分检查是否包含在 [l, r]区间,复杂度 (O(q cdot maxf[i]/m cdot logn)) ,取 m = 300 在时空复杂度上均可行。
    vector牛逼就完事了!

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    typedef long long ll;
    
    using namespace std;
    vector<int> ans[310][310];
    int f[50010];
    int maxf;
    vector<int> cnt[50010];
    
    
    int n, q;
    int main() {
    	cin>>n>>q;
    	maxf = 0;
    	for(int i=1;i<=n;i++) {
    		scanf("%d", &f[i]);
    		cnt[f[i]].push_back(i);
    		maxf = max(maxf, f[i]);
    	}
    
    	for(int m=2;m<=300;m++) {
    		for(int i=1;i<=n;i++) {
    			ans[m][f[i]%m].push_back(i);
    		}
    	}
    
    	int l, r, x, m;
    	while(q--) {
    		scanf("%d %d %d %d", &l, &r, &x, &m);
    		if(m==1) {
    			if(x==0)
    				printf("%d
    ", r-l+1);
    			else
    				printf("0
    ");
    			continue;
    		}
    
    		if(m<=300) {
    			int L = lower_bound(ans[m][x].begin(), ans[m][x].end(), l) - ans[m][x].begin();
    			int R = upper_bound(ans[m][x].begin(), ans[m][x].end(), r) - ans[m][x].begin();
    			printf("%d
    ", R - L);
    			continue;
    		}
    
    		ll ans = 0;
    		for(int v=x;v<=maxf;v+=m) {
    			int L = lower_bound(cnt[v].begin(), cnt[v].end(), l) - cnt[v].begin();
    			int R = upper_bound(cnt[v].begin(), cnt[v].end(), r) - cnt[v].begin();
    			ans += R - L;
    		}
    		printf("%lld
    ", ans);
    	}
    
    	return 0;
    } 
    

    F. Forbechenko v Rodvsky

    题意

    1/3 在十进制下的小数表示为 0.33333…,在3进制下为 0.1。给定 (A over B) ,求最小的进制使其表示成小数的位数是有限的。

    思路

    很好想,可以发现A,B约分之和,最小的进制就是B的素因子之积。

    那么问题转化为质因数分解然后一看过了那么多写了个暴力根号n的算法T了。

    队友翻到了Pollard-Rho的板子,然后敲上去就A啦。

    #include<cstdio>
    #include<iostream>
    #include<ctime>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    
    typedef long long ll;
    const int S= 8;
    ll qmul(ll a,ll b,ll c) {
        a %= c;
        b %= c;
        ll ret = 0;
        ll tmp = a;
        while(b) {
            if(b&1) {
                ret += tmp;
                if(ret>c)ret -=c;
            }
            tmp<<=1;
            if(tmp>c)tmp -=c;
            b>>=1;
        }
        return ret;
    }
    ll qpow(ll a,ll n,ll mod) {
        ll ret = 1;
        ll tmp = a%mod;
        while(n) {
            if(n&1)
                ret = qmul(ret,tmp,mod);
            tmp = qmul(tmp,tmp,mod);
            n>>=1;
        }
        return ret;
    }
    // 判断是否是合数
    bool check(ll a,ll n,ll x,ll t) {
        ll ret = qpow(a,x,n);
        ll last = ret;
        for(int i=1;i<=t;++i) {
            ret = qmul(ret,ret,n);
            if(ret==1&&last!=1&&last!=n-1)
                return true;
            last = ret;
        }
        if(ret!=1) return true;
        else return false;
    }
    // ****************************
    // Miller_Rabin算法判断是否是素数
    bool Miller_Rabin(ll n) {
        if(n<2)return 0;
        if(n==2)return 1;
        if((n&1)==0)return 0;
        ll x= n-1;
        ll t =0;
        while((x&1)==0) {
            x>>=1;
            ++t;
        }
        srand(time(NULL));
        for(int i=0;i<S;++i) {
            ll a = rand()%(n-1)+1;
            if(check(a,n,x,t))
                return 0;
        }
        return 1;
    }
    // ***************************
    // pollard_rho算法进行质因数分解
    ll factor[100];
    int tol;
    
    ll gcd(ll a,ll b) {
        ll t;
        while(b) {
            t = a;
            a = b;
            b = t%b;
        }
        if(a>=0)return a;
        else return -a;
    }
    ll pollard_pho(ll x,ll c) {
        ll i=1, k=2;
        srand(time(NULL));
        ll x0 =rand()%(x-1)+1;
        ll y = x0;
        while(1) {
            i++;
            x0 = (qmul(x0,x0,x)+c)%x;
            ll d=gcd(y-x0,x);
            if(d!=1&&d!=x) return d;
            if(y==x0) return x;
            if(i==k) {
                y=x0;
                k+=k;
            }
        }
    }
    void findfac(ll n,int k) {
        if(n==1)return;
        if(Miller_Rabin(n)) {
            factor[tol++] = n;
            return;
        }
        ll p =n;
        int c= k;
        while(p>=n)
            p = pollard_pho(p,c--);
        findfac(p,k);
        findfac(n/p,k);
    }
     
    int main() {
        ll a, b;
    	scanf("%lld %lld", &a, &b);
    	b = b/gcd(a, b);
    	if(b==1) {
            return 0* printf("2
    ");
    	}
     
    	findfac(b, 107);
    	sort(factor, factor+tol);
    	tol = unique(factor, factor+tol) - factor;
    
        ll res = 1;
    	for(int i=0;i<tol;i++) {
            res *= factor[i];
    	}
    	printf("%lld
    ", res);
     
        return 0;
    }
    

    G. Hunting leshys

    题意

    有 n 个部落(那单词啥意思我也不知道),初始每个人是一个部落,每个人有power p[i],有 两种操作,(! i, j) :i成为j的首领;(? i):询问 i 到他的最终首领(根节点)之间的最小权值。

    思路

    一看就是并查集,然后队友演了我,写了假算法。(并不是求整条链上的最小权值所以不可以直接压缩路径),然后告诉我并查集好像做不了,需要树链剖分。。。

    然后我xjb写了就A了。(路径压缩时维护当前节点到根节点之间的最小权值)

    AC代码

    #include<cstdio>
    #include<iostream>
    typedef long long ll;
    using namespace std;
     
    const int N = 1e5+10;
    int arr[N];
    int fa[N];
    int find(int x)
    {
        if(x==fa[x]) return x;
        int root = find(fa[x]);
        arr[x] = min(arr[x], arr[fa[x]]);
        return fa[x] = root;
    }
     
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) {
            scanf("%d",&arr[i]);
            fa[i] = i;
        }
        while(m--) {
            char op[3];
            scanf("%s", op);
            if(op[0]=='?') {
                int a;
                scanf("%d",&a);
                int fa = find(a);
                printf("%d
    ", arr[a]);
            }
            else {
                int a, b;
                scanf("%d%d",&a, &b);
                fa[b] = a;
            }
        }
        return 0;
    }
    

    H. Course recommendation

    题意

    队友写的,据说是SB题,题意没表述清楚白白浪费一小时。。。

    I. Sobytiynyy Proyekt Casino

    题意

    看了很久,根据样例大概理解为:有 n 个 玩家,每个人有一个整数对 (ai, bi),玩家 i 离开时可以获得 (sum_{j=1}^{i} a_j - b_i) 硬币,每个玩家可以在随意离开游戏。现在你可以决定玩家的顺序,求所有玩家获取的最多硬币的最小值。

    思路

    卡了半天,大概证明出来 按照 bi 递增的顺序安排,可以使玩家收益最小。

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
     
    struct node {
        ll a, b;
        bool operator<(const node& n) const {
            return b<n.b;
        }
    }arr[100010];
    int main() {
        int n; cin>>n;
        for(int i=1;i<=n;i++) {
            scanf("%lld %lld", &arr[i].a, &arr[i].b);
        }
     
        sort(arr+1, arr+1+n);
        ll sum = arr[1].a, ans = arr[1].a-arr[1].b;
        for(int i=2;i<=n;i++) {
            sum += arr[i].a;
            ans = max(ans, sum-arr[i].b);
        }
        printf("%lld
    ", ans);
        return 0;
    }
    

    K. Poor Folk

    题意

    给了一堆值,求这些值不能组成的最小整数。

    思路

    队友A的,稍后理解一下。

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll arr[500010];
    int main()
    {
        int n;cin>>n;
        for(int i=1;i<=n;++i)
            cin>>arr[i];
        sort(arr+1,arr+1+n);
        ll now = 0;
        for(int i=1;i<=n;++i)
        {
            if(now+1<arr[i])
            {
                cout<<now+1<<endl;
                break;
            }
            else
                now+=arr[i];
            if(i==n)
                cout<<now+1<<endl;
        }  
        return 0;
    }
    

    (完)

  • 相关阅读:
    网宿科技股份有限公司投资者关系活动记录表(2014.3.30)
    网宿科技投资者关系活动记录2016年10月31日
    [转载]20131206 网宿科技电话交流会纪要
    strlcpy和strlcat
    114 的 dns 的解析测试
    大批量数据读写
    ART——一个轻量级的web报表工具
    递归删除.svn文件
    SA常用命令
    淘女郎团队敏捷开发实践2011上半年回顾
  • 原文地址:https://www.cnblogs.com/izcat/p/11594771.html
Copyright © 2011-2022 走看看