zoukankan      html  css  js  c++  java
  • XVII Open Cup named after E.V. Pankratiev. XXI Ural Championship

    A. Apple

    按题意模拟即可。

    #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;
    vector<int>a[N];
    
    int ind1 = 0, ind1num = 0;
    int ind2num = 0;
    int ind3 = 0, ind3num = 0;
    bool vis[N];
    int ind[N];
    
    int cnt;
    bool dfs1(int x, int fa)
    {
        ++cnt;
        vis[x] = 1;
        for(auto y : a[x])if(y != fa)
        {
            if(!vis[y])
            {
                if(!dfs1(y, x))return 0;
            }
            else if(y != ind3)return 0;
        }
        return 1;
    }
    
    void dfs3(int x, int fa)
    {
        ++cnt;
        vis[x] = 1;
        for(auto y : a[x])if(y != fa)
        {
            if(!vis[y])
            {
                dfs3(y, x);
            }
        }
    }
    
    bool solve()
    {
        if(ind1num != 1)return 0;
        if(ind2num != n - 2)return 0;
        if(ind3num != 1)return 0;
    
        cnt = 0;
        vis[ind3] = true;
        if(!dfs1(ind1, 0))return 0;
        dfs3(ind3, 0);
        if(cnt != n)return 0;
    
        return 1;
    }
    int main()
    {
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    	while(~scanf("%d%d", &n, &m))
    	{
            for(int i = 1; i <= n; ++i)
            {
                a[i].clear();
                ind[i] = 0;
                vis[i] = 0;
            }
            for(int i = 1; i <= m; ++i)
            {
                int x, y; scanf("%d%d", &x, &y);
                a[x].push_back(y);
                a[y].push_back(x);
                ++ind[x];
                ++ind[y];
            }
            ind1 = 0, ind1num = 0;
            ind2num = 0;
            ind3 = 0, ind3num = 0;
            for(int i = 1; i <= n; ++i)
            {
                if(ind[i] == 1)
                {
                    ++ind1num;
                    ind1 = i;
                }
                else if(ind[i] == 2)
                {
                    ++ind2num;
                }
                else if(ind[i] == 3)
                {
                    ++ind3num;
                    ind3 = i;
                }
            }
            puts(solve() ? "Yes" : "No");
    	}
    
    	return 0;
    }
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    9 9
    1 2
    2 3
    3 5
    5 6
    6 4
    4 7
    1 7
    7 9
    8 9
    
    5 5
    1 2
    2 3
    1 3
    1 4
    1 5
    
    4 4
    1 2
    2 3
    1 3
    1 4
    
    5 4
    1 2
    2 3
    1 3
    1 4
    
    
    */
    

      

    B. Bar charts

    关于序列的前缀和建立差分约束系统,SPFA判断是否存在负环。

    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    const int N=12222,M=1000000,E=10000000,inf=~0U>>1;
    int n,i,g[N],v[M],w[M],nxt[M],ed,d[N];
    int x,h,t,q[E];
    int vis[N],in[N];
    inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;nxt[ed]=g[x];g[x]=ed;}
    inline void make(int x,int y,int z){
        //x-y=z
        add(y,x,z);
        add(x,y,-z);
    }
    void gao(){
        int k,b,s;
        scanf("%d%d%d",&k,&b,&s);
        make(b-1,0,0);
        for(int i=b+k*s;i<=n;i++)make(i,i-1,0);
        for(int i=1;i<=k;i++){
            int l=b+(i-1)*s,r=b+i*s;
            int o;
            scanf("%d",&o);
            //s[r-1]-s[l-1]
            make(r-1,l-1,o);
        }
    }
    void NO(){
        puts("No");
        exit(0);
    }
    inline void ext(int x,int y){
        if(y<0)NO();
        if(y>=d[x])return;
        d[x]=y;
        if(!in[x]){
            in[x]=1;
            vis[x]++;
            if(vis[x]>=n)NO();
            q[++t]=x;
            if(t>=E-10)NO();
        }
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        n=11111;
        for(i=0;i<n;i++)add(i+1,i,0);
        gao();
        gao();
        for(i=0;i<=n;i++){
            d[i]=inf;
        }
        h=1,t=0;
        ext(0,0);
        while(h<=t){
            x=q[h++];
            for(i=g[x];i;i=nxt[i])ext(v[i],d[x]+w[i]);
            in[x]=0;
        }
        puts("Yes");
    }
    

      

    C. Construction sets

    二分答案,二进制拆分背包+bitset检验。

    #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 = 55, 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, mn, mx;
    int m[N], c[N];
    bitset<10005>f;
    bool check(int K)
    {
        f.reset(); f[0] = 1;
        for(int i = 1; i <= n; ++i)
        {
            int tot = c[i] / K;
            int g = 1;
            LL v = m[i];
            while(tot)
            {
                if(v > mx)break;
                f |= f << v;
                tot -= g;
                g = min(g * 2, tot);
                v = (LL)m[i] * g;
            }
        }
        for(int j = mn; j <= mx; ++j)
        {
            if(f[j])return 1;
        }
        return 0;
    }
    int main()
    {
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    	while(~scanf("%d%d%d", &n, &mn, &mx))
    	{
            for(int i = 1; i <= n; ++i)
            {
                scanf("%d%d", &m[i], &c[i]);
            }
            int l = 0;
            int r = 1e6;
            while(l < r)
            {
                int mid = (l + r + 1) >> 1;
                if(check(mid))
                {
                    l = mid;
                }
                else
                {
                    r = mid - 1;
                }
            }
            printf("%d
    ", l);
    	}
    
    	return 0;
    }
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    3 12 13
    3 8
    4 6
    7 9
    
    */
    

      

    D. Dinner party

    $f[i][j]$表示面积和为$i$的矩形,周长和为$j$是否有可能,bitset加速。

    #include<cstdio>
    #include<bitset>
    using namespace std;
    const int N=1010,M=2010;
    int T,n,m,i,j,x,y,cnt;
    bitset<M>f[N];
    void solve(){
        scanf("%d%d",&n,&m);
        if(m%2){
            puts("No");
            return;
        }
        m/=2;
        if(f[n][m]==0){
            puts("No");
            return;
        }
        puts("Yes");
        int cnt=0;
        static int q[100000][2];
        while(n){
            int X=0,Y=0;
            for(x=1;x<=n;x++){
                for(y=1;y*x<=n;y++)if(x+y<=m)if(f[n-x*y][m-x-y]){
                    X=x,Y=y;
                    break;
                }
                if(X)break;
            }
            q[++cnt][0]=X;
            q[cnt][1]=Y;
            n-=X*Y;
            m-=X+Y;
        }
        printf("%d
    ",cnt);
        for(int i=1;i<=cnt;i++)printf("%d %d
    ",q[i][0],q[i][1]);
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        //scanf("%d%d",&n,&m);
        n=1000;
        m=2000;
        f[0][0]=1;
        for(i=0;i<=n;i++)
            for(x=1;x+i<=n;x++)
                for(y=1;x*y+i<=n;y++)
                    f[i+x*y]|=f[i]<<(x+y);
        scanf("%d",&T);
        while(T--)solve();
    }
    

      

    E. Expression on dice

    若要构造$=$,则在两侧构造$0$即可,否则随意构造。

    //
    //  main.cpp
    //  opencup 10378 E
    //
    //  Created by luras on 2017/9/14.
    //  Copyright © 2017年 luras. All rights reserved.
    //
    
    #define ms(x, y) memset(x, y, sizeof(x))
    #define mc(x, y) memcpy(x, y, sizeof(x))
    #define lson o << 1, l, mid
    #define rson o << 1 | 1, mid + 1, r
    #define ls o << 1
    #define rs o << 1 | 1
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<stack>
    #include<time.h>
    #include<vector>
    #include<list>
    #include<set>
    #include<iostream>
    #include<stdlib.h>
    #include<string>
    #include<algorithm>
    #pragma comment(linker,"/STACK:102400000,102400000")
    template <class T> inline void gmax(T &a, T b){if(b > a) a = b;}
    template <class T> inline void gmin(T &a, T b){if(b < a) a = b;}
    using namespace std;
    const int N = 1e6 + 10, M = 2e6 + 10, Z = 1e9 + 7, maxint = 2147483647, ms1 = 16843009, ms31 = 522133279, ms63 = 1061109567, ms127 = 2139062143;
    const double PI = acos(-1.0), eps = 1e-8;
    typedef long long LL;
    void fre()
    {
        freopen("/Users/luras/Desktop/in.txt", "r", stdin);
        freopen("/Users/luras/Desktop/out.txt", "w", stdout);
    }
    const int INF = 1e9;
    int casenum, casei;
    
    int priv[N];
    double calc(double a, double b, char op)
    {
        if(op == '+') return a + b;
        if(op == '-') return a - b;
        if(op == '*') return a * b;
        if(op == '/') return a / b;
        return 0;
    }
    
    
    double calculate(string str)
    {
        stack<double> num;
        stack<char> oper;
        priv['+'] = priv['-'] = 3;
        priv['*'] = priv['/'] = 2;
        priv['('] = 10;
        double x, y, t = 0;
        int i; char last = 0;
        for(i = 0; i < str.length(); i ++){
            if(isdigit(str[i])){
                num.push(atof(str.c_str() + i));
                for(; i + 1 < str.length() && isdigit(str[i + 1]); i ++);
                if(i + 1 < str.length() && str[i + 1] == '.')
                    for(i ++; i + 1 < str.length() && isdigit(str[i + 1]); i ++);
            }
            else if(str[i] == '('){
                oper.push(str[i]);
            }
            else if(str[i] == ')'){
                while(oper.top() != '('){
                    y = num.top(); num.pop();
                    x = num.top(); num.pop();
                    char op = oper.top();
                    oper.pop();
                    num.push(calc(x, y, op));
                }
                oper.pop();
            }
            else if(str[i] == '-' && (last == 0 || last == '(')){
                num.push(0.0);
                oper.push('-');
            }
            else if(priv[str[i]] > 0){
                while(oper.size() > 0 && priv[str[i]] >= priv[oper.top()]){
                    y = num.top(); num.pop();
                    x = num.top(); num.pop();
                    char op = oper.top();
                    oper.pop();
                    num.push(calc(x, y, op));
                }
                oper.push(str[i]);
            }else continue;
            last = str[i];
        }
        while(oper.size() > 0){
            y = num.top(); num.pop();
            x = num.top(); num.pop();
            char op = oper.top();
            oper.pop();
            num.push(calc(x, y, op));
        }
        return num.top();
    }
    
    map<int, bool> mop;
    vector<int> num;
    vector<char> sym;
    int lft, rgt, zero, divi, typ;
    
    
    const string sta[6][6] ={
        {"=", "<", ">", "!=", "<=", ">="},
        {"4", "+", "-", "(", "(", ")"},
        {"0", "/", "/", "/", "8", "+"},
        {"2", "3", "4", "5", "-", ")"},
        {"+", "-", "*", "/", "1", "9"},
        {"6", "7", "+", "-", "(", ")"}
    };
    
    
    void ask(int o)
    {
        char ch;
        if(o == 2){
            puts("2");
            fflush(stdout);
            scanf(" %c", &ch);
            //ch = sta[1][rand() % 6][0];
            //cout << "A: " << ch;
            if(ch == '(') lft ++;
            else if(ch == ')') rgt ++;
            else if(ch == '4') {
                num.push_back(ch);
                if(mop[ch] == 0){
                    mop[ch] = 1;
                    typ ++;
                }
            }
            else sym.push_back(ch);
        }
        else if(o == 3){
            puts("3");
            fflush(stdout);
            scanf(" %c", &ch);
            //ch = sta[2][rand() % 6][0];
            //cout << "A: " << ch;
            
            if(ch == '0') zero ++;
            else if(ch == '8') {
                num.push_back(ch);
                if(mop[ch] == 0){
                    mop[ch] = 1;
                    typ ++;
                }
            }
            else if(ch == '/') divi ++;
            else sym.push_back(ch);
        }
        else if(o == 4){
            puts("4");
            fflush(stdout);
            //ch = sta[3][rand() % 6][0];
            //cout << "A: " << ch;
            
            scanf(" %c", &ch);
            if(ch == '-') sym.push_back(ch);
            else if(ch == ')') rgt ++;
            else {
                num.push_back(ch);
                if(mop[ch] == 0){
                    mop[ch] = 1;
                    typ ++;
                }
            }
        }
    }
    
    
    string ans;
    string s;
    string ss;
    
    int sgn(double x)
    {
        if(fabs(x) < eps) return 0;
        return x > 0 ? 1 : -1;
    }
    
    bool choose()
    {
        s = "";
        int DIV = divi, ZERO = zero;
        int n = num.size(), m = sym.size() + DIV;
        int bas = (n + ZERO) / (m + 1);
        int mo = (n + ZERO) - (m + 1) * bas;
        int t = 0, j = -1, k = -1;
        for(int i = 0; i < m + 1; i ++){
            if(mo){
                if(j + 1 >= n) return 0; // 必须得放前导0了
                s += num[++ j]; ++ t;
                while(t <= bas && ZERO){
                    s += '0'; t ++; ZERO --;
                }
                while(t <= bas){
                    s += num[++ j]; t ++;
                }
                mo --;
                t = 0;
            }
            else{
                if(j + 1 >= n) return 0;
                s += num[++ j]; ++ t;
                while(t < bas && ZERO){
                    s += '0'; t ++; ZERO --;
                }
                while(t < bas){
                    s += num[++ j]; t ++;
                }
                t = 0;
            }
            if(DIV){
                s += '/';
                DIV --;
            }
            else{
                if(k + 1 < sym.size())s += sym[++ k];
            }
        }
        return 1;
    }
    
    bool check(int o)
    {
        if(o == 0){
            zero -= 2; lft --; rgt --; divi --;
            if(!choose()) {zero += 2; lft ++; rgt ++; divi ++; return 0;}
            if(calculate(s) != 0){
                ans = "";
                for(int i = 0; i < lft; i ++) ans += '(';
                ans += '0';
                for(int i = 0; i < rgt; i ++) ans += ')';
                ans += "=0/(" + s + ')';
            }
            else {zero += 2; lft ++; rgt ++; divi ++; return 0;}
        }
        else{
            zero --;
            if(!choose()) {zero ++;return 0;}
            double tmp = calculate(s);
            if(sgn(tmp) != 0){
                if(ss[0] == '<' && sgn(tmp) > 0 || ss[0] == '>' && sgn(tmp) < 0){
                    ans = "";
                    for(int i = 0; i < lft; i ++) ans += '(';
                    ans += '0';
                    for(int i = 0; i < lft; i ++) ans += ')';
                    ans += ss + s;
                }
                else{
                    ans = "";
                    for(int i = 0; i < lft; i ++) ans += '(';
                    ans += s;
                    for(int i = 0; i < lft; i ++) ans += ')';
                    ans += ss + '0';
                }
            }
            else if(ss == "!="){
                ans = "";
                for(int i = 0; i < lft; i ++) ans += '(';
                ans += '0';
                for(int i = 0; i < lft; i ++) ans += ')';
                ans += ss + s;
                
            }
            else {zero ++; return 0;}
        }
        return 1;
    }
    
    int main()
    {
        srand(time(NULL));
        //fre();
        puts("1");
        fflush(stdout);
        cin >> ss;
        //ss = sta[0][rand() % 6];
        //cout << ss << endl;
        lft = rgt = zero = divi = typ = 0;
        int tim = 0;
        while(1){
            if(++ tim == 1000){
                int go = 1;
            }
            if(zero < (ss[0] == '=' ? 2 : 1) || divi == 0){
                ask(3);
            }
            else if(lft < rgt || lft == 0){
                ask(2);
            }
            else if(num.size() - 2 < sym.size() || rgt < lft){
                ask(4);
            }
            else {
                if(check(ss[0] == '=' ? 0 : 1)) break;
                ask(4);
            }
        }
        printf("0 ");
        cout << ans << endl;
        fflush(stdout);
        return 0;
    }
    
    /*
     
     
     题意:
     
     类型:
     
     分析:
     
     优化:
     
     trick:
     
     数据:
     
     Sample Input
     
     Sample Output
     
     >=
     + / / + 8 0 ) ( ) ( - - 5 5 5 - 4 4 4 - 5 3
     
     */
    

      

    F. Flight trip

    留坑。

    G. Glasses with solutions

    找出的子集需要满足$bsum m-asum t=0$,折半搜索即可。

    #include<cstdio>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int N=40;
    int n,m,A,B,i,x,y,a[N];map<ll,ll>f;
    ll ans;
    void dfsl(int x,ll y){
        if(x==m){f[y]++;return;}
        dfsl(x+1,y+a[x]);
        dfsl(x+1,y);
    }
    void dfsr(int x,ll y){
        if(x==n){ans+=f[-y];return;}
        dfsr(x+1,y+a[x]);
        dfsr(x+1,y);
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        scanf("%d%d%d",&n,&A,&B);
        for(i=0;i<n;i++){
            scanf("%d%d",&x,&y);
            a[i]=x*B-A*y;
        }
        m=n/2;
        dfsl(0,0);
        dfsr(m,0);
        ans--;
        printf("%lld",ans);
    }
    

      

    H. Hamburgers

    对于每个汉堡,$O(2^6)$枚举所有它可以满足的口味,然后对于每个人判断是否满足即可。

    时间复杂度$O(msum a+2^6sum b)$。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int N=55555;
    int n,m,i,j,k,x,ans[N],mx[N],b[N];
    vector<int>a[N];
    bool v[(1<<26)+5];
    inline int get(){
        static char s[1000];
        scanf("%s",s);
        int t=0,len=strlen(s);
        for(int i=0;i<len;i++)t|=1<<(s[i]-'a');
        return t;
    }
    inline void make(int x,int y){
        for(int i=x;i;i=(i-1)&x)v[i]=y;
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d",&k);
            while(k--){
                x=get();
                a[i].push_back(x);
            }
            ans[i]=1;
        }
        scanf("%d",&m);
        for(i=1;i<=m;i++){
            scanf("%d",&k);
            for(j=1;j<=k;j++)b[j]=get();
            for(j=1;j<=k;j++)make(b[j],1);
            for(j=1;j<=n;j++){
                int t=0;
                for(x=0;x<a[j].size();x++)if(v[a[j][x]])t++;
                if(t>mx[j])mx[j]=t,ans[j]=i;
            }
            for(j=1;j<=k;j++)make(b[j],0);
        }
        for(i=1;i<=n;i++)printf("%d
    ",ans[i]);
    }
    /*
    5
    1
    a
    3
    a
    ba
    cb
    3
    vba
    d
    ba
    3
    ca
    da
    da
    3
    as
    ba
    af
    2
    4
    abc
    abcd
    a
    a
    2
    abcdef
    abcdev
    */
    

      

    I. Intricate path

    留坑。

    J. Jumps through the Hyperspace

    显然到每个点的时间越早越好,对于每种传送门预处理出每种余数下的最优等待时间即可。

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    typedef pair<int,int>P;
    const int N=2010,inf=~0U>>1;
    int n,m,st,i,j,a[N],b[N],c[N],d[N],w[N][N];
    int f[N];
    char g[N][N],op[N];
    priority_queue<P,vector<P>,greater<P> >q;
    inline void ext(int x,int y){
        if(f[x]>y)q.push(P(f[x]=y,x));
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        scanf("%d%d%d",&n,&m,&st);
        while(m--){
            scanf("%s",op);
            int o=op[0];
            scanf("%d%d%d%d",&a[o],&b[o],&c[o],&d[o]);
            for(i=0;i<c[o];i++){
                w[o][i]=inf;
                for(j=0;j<c[o];j++)w[o][i]=min(w[o][i],(a[o]*(i+j)+b[o])%c[o]+d[o]+j);
            }
        }
        for(i=1;i<=n;i++)scanf("%s",g[i]+1);
        for(i=1;i<=n;i++)f[i]=inf;
        ext(1,st);
        while(!q.empty()){
            P t=q.top();q.pop();
            if(f[t.second]<t.first)continue;
            for(i=1;i<=n;i++)if(g[t.second][i]!='.')
                ext(i,t.first+w[g[t.second][i]][t.first%c[g[t.second][i]]]);
        }
        if(f[n]==inf)puts("-1");else 
        printf("%d",f[n]-st);
    }
    

      

    K. King’s island

    暴力搜索出一个上凸壳,然后翻转拼接起来得到完整的多边形即可。

    #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 = 1010, 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;
    struct B
    {
        int x, y;
        bool operator < (const B & b)const
        {
            //y/x > b.y/b.x
            return y * b.x > x * b.y;
        }
    };
    B p[100000]; int g;
    int f[N][N][62];
    struct A
    {
        int x, y, z;
    };
    bool bingo[60];
    vector<B>ans[60];
    
    void getvt(int x, int y, int v, vector<B>&vt, int DX, int DY)
    {
        if(v == 0)return;
        int o = f[x][y][v];
        if(f[x - p[o].x][y - p[o].y][v] == o)
        {
            getvt(x - p[o].x, y - p[o].y, v, vt, DX + p[o].x, DY + p[o].y);
        }
        else
        {
            vt.push_back({p[o].x + DX, p[o].y + DY});
            getvt(x - p[o].x, y - p[o].y, v - 1, vt, 0, 0);
        }
    }
    
    void init()
    {
        for(int i = 1; i <= 200; ++i)
        {
            for(int j = i + 1; j <= 200; ++j)if(__gcd(i, j) == 1)
            {
                int W = (i * i + j * j);
                int w = sqrt(W);
                if(w * w == W)
                {
                    p[++g] = {i, j};
                    p[++g] = {j, i};
                }
            }
        }
        sort(p + 1, p + g + 1);
        //printf("%d
    ", g);
    
        MS(f, 0);
        f[0][0][0] = 1;
        for(int i = 0; i <= 500; ++i)
        {
            for(int j = 0; j <= 500; ++j)
            {
                for(int v = 29; v >= 0; --v)if(f[i][j][v])
                {
                    //
                    int k = f[i][j][v];
                    auto &it = f[i + p[k].x][j + p[k].y][v];
                    if(it == 0)it = k;
                    //
                    for(int k = f[i][j][v] + 1; k <= g; ++k)
                    {
                        auto &it = f[i + p[k].x][j + p[k].y][v + 1];
                        if(it == 0)it = k;
                    }
                    if(i == 0 || j == 0)continue;
                    for(int u = 1; u + v <= 30; ++u)if(f[i][j][u] && f[i][j][u] != f[i][j][v])
                    {
                        if(!bingo[u + v])
                        {
                            bingo[u + v] = 1;
                            vector<B>up, down;
                            getvt(i, j, u, up, 0, 0);
                            getvt(i, j, v, down, 0, 0);
                            int x = i;
                            int y = j;
                            //printf("%d %d %d
    ", u + v, up.size(), down.size());
                            //puts("up------------");
                            for(int r = 0; r < up.size(); ++r)
                            {
                                x -= up[r].x;
                                y -= up[r].y;
                                ans[u + v].push_back({x, y});
                                //printf("%d %d
    ", up[r].x, up[r].y);
                            }
                            //puts("down------------");
                            for(int r = 0; r < down.size(); ++r)
                            {
                                x += down[r].x;
                                y += down[r].y;
                                ans[u + v].push_back({x, y});
                                //printf("%d %d
    ", down[r].x, down[r].y);
                            }
                            //puts("ans------");
                            for(auto w : ans[u + v])
                            {
                                //printf("%d %d
    ", w.x, w.y);
                            }
                            int pasue = 1;
                        }
                    }
                }
            }
        }
        for(int i = 1;i <= 30; ++i)
        {
            //printf("%d
    ", bingo[i]);
        }
    }
    int main()
    {
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
        init();
    	while(~scanf("%d", &n))
    	{
    	    if(n == 3)
            {
                puts("0 0
    4 3
    -20 21");
                continue;
            }
            for(auto it : ans[n])
            {
                printf("%d %d
    ", it.x, it.y);
            }
    	}
    
    	return 0;
    }
    /*
    【trick&&吐槽】
    
    
    【题意】
    
    
    【分析】
    
    
    【时间复杂度&&优化】
    28 195
    9 15
    -116 178
    4
    20 21
    1 -159
    -236 -11
    -92 6
    5
    20 50
    3 -94
    -16 -274
    -236 18
    -92 35
    
    
    */
    

      

    L. Lexica

    无视同一行/同一列的两个格子的位置关系,只需要在它们不相同时将方案数乘$2$,如此一来只关心每一行/每一列有多少格子没满足。

    设$f[i][j][S][k]$表示考虑到$(i,j)$,每一列剩余情况为$S$,第$i$行还有$k$个格子需要填充时的方案数,然后逐格转移即可。

    时间复杂度$O(n3^n)$。

    #include<cstdio>
    typedef unsigned long long ll;
    const int N=18,M=1600000;
    int n,m,all,i,j,k,x,y,z,A,B,C,S,o,p[N],mask,cnt[N];
    char a[N][N];
    int e;
    ll f[2][M][3],mul;
    int w[M];
    inline void clr(){
        for(int i=0;i<=mask;i++)for(int j=0;j<3;j++)f[e^1][i][j]=0;
    }
    inline void nxt(){
        //for(int i=0;i<=mask;i++)for(int j=0;j<3;j++)f[i][j]=g[i][j];
    }
    inline int get(int S,int x){
        return S/p[x]%3;
    }
    void dfs(int x,int y,int z){
    		if(x==n){
    			w[y]=z;
    			return;
    		}
    		for(int i=0;i<3;i++)dfs(x+1,y*3+i,z*2+(!!i));
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        scanf("%d",&n);
        m=n+2;
        for(i=0;i<m;i++)scanf("%s",a[i]);
        mul=1;
        for(p[0]=i=1;i<N;i++)p[i]=p[i-1]*3;
        all=p[n];
        for(i=1;i<=n;i++){
            if(a[0][i]!='#'&&a[m-1][i]!='#'&&a[0][i]!=a[m-1][i])mul*=2;
            if(a[i][0]!='#'&&a[i][m-1]!='#'&&a[i][0]!=a[i][m-1])mul*=2;
            if(a[i][0]!='#')cnt[i]++;
            if(a[i][m-1]!='#')cnt[i]++;
            if(a[0][i]!='#')mask+=p[i-1];
            if(a[m-1][i]!='#')mask+=p[i-1];
        }
        dfs(0,0,0);
        f[0][mask][0]=mul;
        for(i=1;i<=n;i++){
            clr();
            int o=cnt[i];
            for(A=0;A<=mask;A++)f[e^1][A][o]=f[e][A][0];
            e^=1;
            for(j=0;j<n;j++)if(a[i][j+1]=='.'){
                clr();
                for(S=0;S<=mask;S++){
                		if(w[S]>>j&1)for(k=0;k<=o;k++)if(f[e][S][k])f[e^1][S-p[j]][k]+=f[e][S][k];
                		for(k=1;k<=o;k++)if(f[e][S][k])f[e^1][S][k-1]+=f[e][S][k];
                }
                e^=1;
            }
        }
        printf("%llu",f[e][0][0]);
    }
    /*
    5
    ##ARRR#
    H.#.##S
    Y.....E
    O.#.#.E
    ##....E
    ###.#.E
    #XNT#A#
    */
    

      

    M. Maximal paths

    树形DP求出每个点内部从叶子往上、从上往下的最大数字串即可。需要手写高精度。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef unsigned long long ll;
    typedef __int128 lll;
    const int N=10000010,M=50;
    const ll MO=1000000000000000000ULL;
    int n,i;char a[N];
    struct P{
        ll v[3];
        P(){v[0]=v[1]=v[2]=0;}
        P operator+(int b){
            P c;
            for(int i=0;i<3;i++)c.v[i]=v[i];
            c.v[0]+=b;
            for(int i=0;i<2;i++)if(c.v[i]>=MO){
                c.v[i+1]+=c.v[i]/MO;
                c.v[i]-=MO;
            }
            return c;
        }
        P operator+(const P&b){
            P c;
            for(int i=0;i<3;i++)c.v[i]=v[i]+b.v[i];
            for(int i=0;i<2;i++)if(c.v[i]>=MO){
                c.v[i+1]+=c.v[i]/MO;
                c.v[i]-=MO;
            }
            return c;
        }
        P operator*(int b){
            P c;
            for(int i=0;i<3;i++)c.v[i]=v[i]*b;
            for(int i=0;i<2;i++)c.v[i+1]+=c.v[i]/MO,c.v[i]%=MO;
            c.v[2]%=MO;
            return c;
        }
        P operator*(const P&b){
            P c;
            static lll f[3];
            f[0]=f[1]=f[2]=0;
            for(int i=0;i<3;i++)if(v[i])for(int j=0;i+j<3;j++)if(b.v[j])f[i+j]+=(lll)v[i]*b.v[j];
            for(int i=0;i<2;i++)if(f[i]>=MO)f[i+1]+=f[i]/MO,f[i]%=MO;
            if(f[2]>=MO)f[2]%=MO;
            for(int i=0;i<3;i++)c.v[i]=f[i];
            return c;
        }
        void up(const P&b){//max=
            int i;
            for(i=2;~i;i--)if(b.v[i]!=v[i])break;
            if(i<0)return;
            if(b.v[i]<v[i])return;
            for(i=0;i<3;i++)v[i]=b.v[i];
        }
        void write(){
            int i=2;
            while(i&&!v[i])i--;
            printf("%llu",v[i]);
            for(int j=i-1;~j;j--)printf("%018llu",v[j]);
            puts("");
        }
    }f[M],g[M],p[M],ans,ff,gg,mx[M];
    int d[M];
    unsigned int seed,base;
    void dfs(int x,int k){
        f[k]=g[k]=mx[k]=P();
        d[k]=0;
        for(int i=0;i<2;i++){
            int y=x<<1|i;
            if(y>n)continue;
            dfs(y,k+1);
            ff=(f[k+1]*10)+((int)a[y]);
            gg=g[k+1]+(p[d[k+1]]*((int)a[y]));
            mx[k].up((ff*p[d[k]])+g[k]);
            mx[k].up((f[k]*p[d[k+1]+1])+gg);
            /*if(x==1){
                puts("debug");
                ff.write();
                f[k].write();
            }*/
            f[k].up(ff);
            g[k].up(gg);
            d[k]=max(d[k],d[k+1]+1);
            /*if(x==1){
                puts("debug");
                ff.write();
                f[k].write();
            }*/
        }
       /* printf("%d:
    ",x);
        f[k].write();
        g[k].write();
        mx[k].write();*/
        ans=ans+mx[k];
    }
    int main(){
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        scanf("%d%u",&n,&seed);
        base=(1U<<31)-1;
        p[0].v[0]=1;
        for(i=1;i<M;i++)p[i]=p[i-1]*10;
        for(i=1;i<=n;i++){
            a[i]=((seed&base)>>16)%9+1;
            seed=seed*1103515245+12345;
            //printf("%d
    ",a[i]); i and i/2
        }
        dfs(1,0);
        ans.write();
    }
    

      

  • 相关阅读:
    闭关
    我现在很好
    asp.net看不明白怎么办?
    中秋节
    今天很开心
    偶尔伤感
    现在是10月4日了!
    2006的最后一天
    十多天都不写博客了
    呵呵  最近很忙  但是很充实!
  • 原文地址:https://www.cnblogs.com/clrs97/p/7524291.html
Copyright © 2011-2022 走看看