zoukankan      html  css  js  c++  java
  • XVII Open Cup named after E.V. Pankratiev. GP of Tatarstan

    A. Arithmetic Derivative

    形如$p^p(p是质数)$的数的比值为$1$,用$k$个这种数相乘得到的数的比值为$k$,爆搜即可。

    #include<cstdio>
    #include<algorithm>
    typedef unsigned long long ll;
    int K,cnt,all;ll n,i,q[100000],ans[1000000];
    ll po(ll a,ll b){
        ll t=1;
        while(b--){
            if(t>n/a)return n+1;
            t*=a;
        }
        return t;
    }
    bool isprime(ll n){
        for(ll i=2;i<n;i++)if(n%i==0)return 0;
        return 1;
    }
    void dfs(int x,ll y,int k){
        if(y>n)return;
        //printf("%d %llu %d
    ",x,y,k);
        if(k==K){
            ans[++all]=y;
            return;
        }
        if(x>cnt)return;
        dfs(x+1,y,k);
        if(y<=n/q[x])dfs(x,y*q[x],k+1);
    }
    int main(){
        scanf("%d%llu",&K,&n);
        for(i=2;;i++){
            if(po(i,i)>n)break;
            if(isprime(i))q[++cnt]=po(i,i);
        }
        dfs(1,1,0);
        printf("%d
    ",all);
        std::sort(ans+1,ans+all+1);
        for(i=1;i<=all;i++)printf("%llu ",ans[i]);
    }
    

      

    B. White Triangle

    留坑。

    C. New Street

    用set维护相同连续段,每次新增贡献时利用多项式求幂,删除贡献则采用多项式求逆。

    D. Clones and Treasures

    贪心,每次不满足条件了就把前面全部舍弃。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    #define MS(x, y) memset(x, y, sizeof(x))
    #define ls o<<1
    #define rs o<<1|1
    typedef long long LL;
    typedef unsigned long long UL;
    typedef unsigned int UI;
    template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
    template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
    const int N = 1e6 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
    template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
    int casenum, casei;
    char s[N];
    int n;
    int main()
    {
    	while(~scanf("%s", s + 1))
    	{
            n = strlen(s + 1);
            int sum = 0, num = 0;
            int ans = 0;
            for(int i = 1; i <= n; ++i)
            {
                int val;
                if(s[i] == 'H')val = 1;
                else val = (s[i] == 'M' ? 0 : -1);
                sum += val;
                num += (val == 0);
                if(sum < 0)
                {
                    sum = num = 0;
                }
                else
                {
                    gmax(ans, num);
                }
            }
            printf("%d
    ", ans);
    	}
    
    	return 0;
    }
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    
    
    */
    

      

    E. Space Tourists

    当$n>k$时答案为$k$。

    否则最优策略是将$k$个数平均分成$n-1$组,每组$size(size-1)$个字符串,外加$k$个两个字符相等的字符串。

    F. Matrix Game

    最小表示法。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    #define MS(x, y) memset(x, y, sizeof(x))
    #define ls o<<1
    #define rs o<<1|1
    typedef long long LL;
    typedef unsigned long long UL;
    typedef unsigned int UI;
    template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
    template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
    const int N = 105, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
    template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
    int casenum, casei;
    int n, m;
    char s[N][N];
    struct A
    {
        string s;
        bool operator < (const A & b)const
        {
            return s < b.s;
        }
    }line[N], list[N];
    int main()
    {
    	while(~scanf("%d%d", &n, &m))
    	{
            for(int i = 1; i <= n; ++i)
            {
                scanf("%s", s[i] + 1);
                line[i].s = s[i] + 1;
            }
            for(int i = 1; i <= m; ++i)
            {
                string now = "";
                for(int j = 1; j <= n; ++j)
                {
                    now = now + s[j][i];
                }
                list[i].s = now;
            }
            sort(line + 1, line + n + 1);
            sort(list + 1, list + m + 1);
    
            string ans = "";
            for(int i = 1; i <= n; ++i)
            {
                string body = "";
                for(int j = n; j >= 1; --j)if(j != i)
                {
                    body = body + line[j].s;
                }
                for(int j = 0; j < m; ++j)
                {
                    string tmp = line[i].s.substr(j)+body+line[i].s.substr(0, j);
                    gmax(ans, tmp);
                }
            }
            for(int i = 1; i <= m; ++i)
            {
                string body = "";
                for(int j = m; j >= 1; --j)if(j != i)
                {
                    body = body + list[j].s;
                }
                for(int j = 0; j < n; ++j)
                {
                    string tmp = list[i].s.substr(j) + body + list[i].s.substr(0, j);
                    gmax(ans, tmp);
                }
            }
    
            int g = ans.size();
            int st = g - 1;
            for(int i = 0; i < g; ++i)if(ans[i] != '0')
            {
                st = i;
                break;
            }
            cout << ans.substr(st) << endl;
    	}
    	return 0;
    }
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    2 3
    000
    001
    
    */
    

      

    G. Milkland

    留坑。

    H. Parallel Relay

    假如知道了所有数,那么可以等效成只有最小值和最大值的情况。

    对于每一段,将所有数翻折到左边后排序,那么最小值和最大值分别是从左往右的第一个未翻折到右侧和翻折到右侧的,共$O(n)$种情况,枚举即可。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100010;
    int n,m,i,j,a[N],b[N],c[N],ans;
    inline int cal(int a,int b,int c,int d){
        int ret=~0U>>1;
        for(int i=0;i<2;i++){
            swap(c,d);
            ret=min(ret,abs(a-c)+abs(c-d)+abs(d-b));
        }
        return ret;
    }
    int solve(int L,int R){
        int i,j;
        int cnt=0;
        for(i=L;i<=R;i++){
            c[++cnt]=b[i];
        }
        for(i=2;i<cnt;i++)c[i]=min(c[i],m-c[i]+1);
        sort(c+2,c+cnt);
        if(cnt==2)return abs(c[1]-c[2]);
        if(cnt==3)return min(abs(c[1]-c[2])+abs(c[2]-c[3]),abs(c[1]-(m-c[2]+1))+abs(m-c[2]+1-c[3]));
        int ret=cal(c[1],c[cnt],c[2],c[cnt-1]);
        ret=min(ret,cal(c[1],c[cnt],m-c[2]+1,m-c[cnt-1]+1));
        for(i=3;i<cnt;i++){
            ret=min(ret,cal(c[1],c[cnt],c[2],m-c[i]+1));
            ret=min(ret,cal(c[1],c[cnt],m-c[2]+1,c[i]));
        }
        return ret;
    }
    int main(){
        scanf("%d%d",&n,&m);
        n++;
        scanf("%d%d",&b[1],&b[n]);
        a[1]=a[n]=1;
        for(i=2;i<n;i++)scanf("%d%d",&a[i],&b[i]);
        for(i=1,j=0;i<=n;i++)if(a[i]==1){
            if(j)ans+=solve(j,i);
            j=i;
        }
        printf("%d",ans);
    }
    /*
    5 8
    2 6
    1 7
    2 3
    1 1
    2 1
    
    5 21
    4 15
    2 5
    2 6
    1 2
    2 2
    
    10 10
    1 10
    2 2
    2 3
    2 4
    2 5
    2 6
    2 7
    2 8
    2 9
    2 10
    */
    

      

    I. Minimum Prefix

    二分答案,然后Hopcroft求二分图最大匹配检验。

    J. Terminal

    $f[i][j]$表示考虑前$i$组,第一辆车上了$j$个人是否可行。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<string>
    #include<ctype.h>
    #include<math.h>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<algorithm>
    #include<time.h>
    using namespace std;
    void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
    #define MS(x, y) memset(x, y, sizeof(x))
    #define ls o<<1
    #define rs o<<1|1
    typedef long long LL;
    typedef unsigned long long UL;
    typedef unsigned int UI;
    template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
    template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
    const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
    template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
    int casenum, casei;
    int n, m, K;
    int a[N];
    int cnt[N], tmp[N];
    bitset<N>f[2020];
    int main()
    {
    	while(~scanf("%d%d%d", &n, &m, &K))
    	{
    	    gmin(K, n);
    	    MS(cnt, 0);
    	    MS(tmp, 0);
            for(int i = 1; i <= n; ++i)
            {
                scanf("%d", &a[i]);
                ++cnt[a[i]];
            }
            f[0][0] = 1;
            int g = 0;
            LL ans = 1e18;
            for(int i = 1; i <= n; ++i)
            {
                ++tmp[a[i]];
                if(tmp[a[i]] == cnt[a[i]])
                {
                    ++g;
                    f[g] = f[g - 1] | (f[g - 1] << cnt[a[i]]);
                    for(int j = 1; j <= K; ++j)if(f[g][j] && n - j <= K)
                    {
                        gmin(ans, (LL)i * j + (LL)n * (n - j));
                    }
                }
            }
            if(ans == 1e18)ans = -1;
            printf("%lld
    ", ans);
    	}
    
    	return 0;
    }
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    
    
    */
    

      

    K. New Tetris

    用线段树加速模拟即可。

    L. Canonical duel

    每个炮塔可以将其同行同列的所有炮塔都激活,因此枚举一个点,然后将上下左右两个连通块合并即可。

    #include<cstdio>
    const int N=2010,M=N*N;
    int n,m,i,j,k,id[N][N],cnt,f[M],size[M];
    int ans=-1,px,py;
    char a[N][N];
    int left[N][N],right[N][N],up[N][N],down[N][N];
    int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
    inline void merge(int x,int y){
        x=F(x),y=F(y);
        if(x==y)return;
        f[x]=y;
    }
    inline void gao(int x,int y){
        int A=up[x][y];
        if(!A)A=down[x][y];
        int B=left[x][y];
        if(!B)B=right[x][y];
        int ret=size[f[A]];
        if(f[A]!=f[B])ret+=size[f[B]];
        if(ret>ans)ans=ret,px=x,py=y;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)scanf("%s",a[i]+1);
        for(i=1;i<=n;i++)for(j=1;j<=m;j++)a[i][j]=a[i][j]=='+';
        for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(a[i][j]){
            id[i][j]=++cnt;
            f[cnt]=cnt;
        }
        for(i=1;i<=n;i++)for(j=1;j<=m;j++){
            left[i][j]=a[i][j]?id[i][j]:left[i][j-1];
            up[i][j]=a[i][j]?id[i][j]:up[i-1][j];
        }
        for(i=n;i;i--)for(j=m;j;j--){
            right[i][j]=a[i][j]?id[i][j]:right[i][j+1];
            down[i][j]=a[i][j]?id[i][j]:down[i+1][j];
        }
        for(i=1;i<=n;i++){
            k=0;
            for(j=1;j<=m;j++)if(a[i][j]){
                if(k)merge(k,id[i][j]);
                k=id[i][j];
            }
        }
        for(i=1;i<=m;i++){
            k=0;
            for(j=1;j<=n;j++)if(a[j][i]){
                if(k)merge(k,id[j][i]);
                k=id[j][i];
            }
        }
        for(i=1;i<=cnt;i++)size[F(i)]++;
        for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(!a[i][j])gao(i,j);
        if(ans<=0)puts("0");else printf("%d
    %d %d",ans,px,py);
    }
    

      

  • 相关阅读:
    统计脚本代码行数
    expr算术运算
    lsof命令
    测试当前机器可以创建多少线程
    守护进程写日志
    文件描述符fd,struct files_struct
    linux查看反汇编
    信号补充
    Windows10获取VS管理员权限总是很烦人
    asp.net中的Filter类型其实是被当作单例的
  • 原文地址:https://www.cnblogs.com/clrs97/p/7669673.html
Copyright © 2011-2022 走看看