栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

ICPC中等思维题——补题(更新中)

ICPC中等思维题——补题(更新中)

文章目录
  • Thinking
    • 2020 南京 H. Harmonious Rectangle
    • 2021 昆明 Parallel Sort
    • 2019 哈尔滨 I. Interesting Permutation
    • 2020 上海 D. Walker

Thinking 2020 南京 H. Harmonious Rectangle
  • Harmonious Rectangle

  • 思路:意识到,当矩形长边大于 9 时,0,1,2 三个数字形成的 00,01,02,10,11,12,20,21,22 一定会出现重复出现,又因为 00,11,22 在前 7 列出现一个后,下一个一出现也会一定有重复。所以当矩形长边大于 7 时一定有解。

    小数据暴力搜索后打表,大数据直接快速幂计算即可。

    //思维题: 容斥原理!!!
    #include
    #define rep(i, a, b) for(int i = (a); i <= (b); i++)
    #define per(i, a, b) for(int i = (a); i >= (b); i--)
    #define ll long long
    #define db double
    #define PII pair
    #define Pi 3.141592653589793
    const int INF = 0x7fffffff;
    const int N = 1e5 + 5;
    const db eps = 1e-10;
    const int mod = 1e9 + 7;
    using namespace std;
    int cas, n, m, a[10][10], ok;
    ll f[10][10], res;
    int power(ll a, ll b, ll mod){  //a 为对应二进制位数需要记录的值,二进制满足即乘
        ll ans = 1;
        if(mod == 1) ans = 0;
        while(b > 0){  //快速幂即转为二进制按位计算
            if(b % 2 == 1){  //x & 1表示: x % 2 == 1
                ans *= a;
                ans %= mod;
            }
            a *= a;
            a %= mod;
            b >>= 1;
        }
        return ans;
    }
    // inline bool check(int n, int m){  //暴力计算后,得到结果,直接打表,此处为暴力计算代码
    //     rep(i, 1, n - 1) rep(j, 1, m - 1)
    //         if((a[i][j] == a[n][j] && a[i][m] == a[n][m]) || (a[i][j] == a[i][m] && a[n][j] == a[n][m])) return 1;
    //     return 0;
    // }
    // void solve(ll nowx, ll nowy, ll n, ll m){
    //     rep(color, 1, 3){
    //         a[nowx][nowy] = color, ok = 0;
    //         if(check(nowx, nowy)){
    //             ok = 1;
    //             res += power(3, (m * (n - nowx) + m - nowy), mod);
    //             res %= mod;
    //         }
    //         int tmpx = nowx, tmpy = nowy;
    //         if(!ok){  //若当前已填数字不能满足条件,才向下一个位置填数
    //             if(tmpy == m && tmpx == n) continue;
    //             if(tmpy == m) tmpx++, tmpy = 1; 
    //             else tmpy++;
    //             solve(tmpx, tmpy, n, m);
    //         }
    //     }
    // }
    int form[8][8] = {{0, 0, 0, 0, 0, 0, 0, 0}, 
        {0, 0, 0, 0, 0, 0, 0, 0}, 
        {0, 0, 15, 339, 4761, 52929, 517761, 4767849}, 
        {0, 0, 339, 16485, 518265, 14321907, 387406809, 460338013}, 
        {0, 0, 4761, 518265, 43022385, 486780060, 429534507, 792294829},       
        {0, 0, 52929, 14321907, 486780060, 288599194, 130653412, 748778899},   
        {0, 0, 517761, 387406809, 429534507, 130653412, 246336683, 579440654}, 
        {0, 0, 4767849, 460338013, 792294829, 748778899, 579440654, 236701429}
    };
    int main(){
        // rep(i, 1, 7){
        //     rep(j, 1, 7){
        //         if(i == 1 || j == 1) f[i][j] = 0;
        //         else if(j < i) f[i][j] = f[j][i];
        //         else{
        //             res = 0;
        //             memset(a, 0, sizeof(a));
        //             solve(1, 1, i, j);
        //             f[i][j] = res;
        //         }
        //     }
        // }
        cin >> cas;
        while(cas--){
            cin >> n >> m;
            if(min(n, m) == 1) cout << 0 << endl;
            //7 = 3 * 3 - 2
            else if(max(n, m) > 7)  //只有大于7才一定会重复,等于7不一定重复
                cout << power(3, n * m, mod) << endl;
            else cout << form[n][m] << endl;
        }
    }
    
    
2021 昆明 Parallel Sort
  • Parallel Sort

  • 思路:由于原数列是 1 ∼ n 1sim n 1∼n 的一个排列,所以没有重复数字,每个数值最终也会与位置编号一一对应。当 s z sz sz 个数字构成一个位置对应的环时,发现一种最多两步便可使所有数值归位的方法。例如:(其中第一步建成逆序排列)

    位置编号12345
    初始值51234
    第一步后54321
    第二步后12345
    #include
    #define rep(i, a, b) for(int i = (a); i <= (b); i++)
    #define per(i, a, b) for(int i = (a); i >= (b); i--)
    #define ll long long
    #define db double
    #define VI vector
    #define PII pair
    #define Pi 3.141592653589793
    const int INF = 0x7fffffff;
    const int N = 1e5 + 5;
    const db eps = 1e-10;
    using namespace std;
    int n, a[N], circnt = 0, vis[N], now, maxn = 0, cnt2 = 0;
    VI cir[N];
    int main(){
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        cin >> n;
        rep(i, 1, n) cin >> a[i];
        memset(vis, 0, sizeof(vis));
        rep(i, 1, n){
            if(vis[i]) continue;
            now = i;  //储存位置编号
            circnt++;
            while(!vis[now]){
                cir[circnt].push_back(now);
                vis[now] = 1;
                now = a[now];  //转移到下一位置
            }
        }
        rep(i, 1, circnt){
            int sz = (int)cir[i].size();
            if(sz == 2) cnt2++;
            maxn = max(maxn, sz);
        }
        if(maxn == 1) cout << 0 << endl;
        else if(maxn == 2){
            cout << 1 << endl << cnt2 << " ";
            rep(i, 1, circnt){
                if((int)cir[i].size() == 1) continue;
                for(auto j : cir[i]) cout << j << " ";
            }
        }
        else{
            cout << 2 << endl;
            //step1: 只变 size(长度) 大于 2 的环
            int k1 = 0;
            rep(i, 1, circnt){
                int sz = (int)cir[i].size();
                if(sz == 1 || sz == 2) continue;
                k1 += (sz - (sz % 2 ? 0 : 2)) / 2;
            }
            cout << k1 << " ";
            rep(i, 1, circnt){
                int sz = (int)cir[i].size();
                if(sz == 1 || sz == 2) continue;
                rep(j, 1, sz / 2 - (sz % 2 ? 0 : 1)){  //输出加交换
                    cout << cir[i][j] << " " << cir[i][sz - j] << " ";
                    swap(cir[i][j], cir[i][sz - j]);
                }
            }
            cout << endl;
            //step2: 变所有 size(长度) 大于 1 的环
            int k2 = 0;
            rep(i, 1, circnt) k2 += (int)cir[i].size() / 2;
            cout << k2 << " ";
            rep(i, 1, circnt){
                int sz = (int)cir[i].size();
                if(sz == 1) continue;
                rep(j, 0, sz / 2 - 1)  //直接输出即可
                    cout << cir[i][j] << " " << cir[i][sz - 1 - j] << " ";
            }
        }
    }
    
2019 哈尔滨 I. Interesting Permutation
  • Interesting Permutation

  • 思路: O ( n ) O(n) O(n)
    ∵ f i = max ⁡ { a i , f i − 1 } , g i = min ⁡ { a i , g i − 1 } ∴ h i = max ⁡ { a i , f i − 1 } − min ⁡ { a i , g i − 1 } 若 a i > f i , h i = a i − g i − 1 > h i − 1 若 g i − 1 < a i < f i , h i = f i − 1 − g i − 1 = h i − 1 若 a i < g i − 1 , h i = f i − 1 − a i > h i − 1 because f_i=max{a_i,f_{i-1}},g_i=min{a_i,g_{i-1}} qquadtherefore h_i=max{a_i,f_{i-1}}-min{a_i,g_{i-1}}\ begin{aligned}&若a_i>f_i,&h_i=a_i-g_{i-1}>h_{i-1}\ &若g_{i-1}h_{i-1}\ end{aligned} ∵fi​=max{ai​,fi−1​},gi​=min{ai​,gi−1​}∴hi​=max{ai​,fi−1​}−min{ai​,gi−1​}​若ai​>fi​,若gi−1​hi−1​hi​=fi−1​−gi−1​=hi−1​hi​=fi−1​−ai​>hi−1​​

    • 因此 h 1 = 0 , h i ≥ h i − 1 h_1=0,h_ige h_{i-1} h1​=0,hi​≥hi−1​ 一定成立,于是无解情况需要充分讨论。

    • 有解时

      • 若 h i > h i − 1 h_i>h_{i-1} hi​>hi−1​,那么 a i a_i ai​ 可以为最大值或最小值两种情况,同时 g i − 1 ∼ f i − 1 g_{i-1}sim f_{i-1} gi−1​∼fi−1​ 变为 g i ∼ f i g_isim f_i gi​∼fi​ ,其中增加 h i − h i − 1 − 1 h_i-h_{i-1}-1 hi​−hi−1​−1 个空位。
      • 若 h i = h i − 1 h_i=h_{i-1} hi​=hi−1​,那么 a i a_i ai​ 只能在 g i − 1 ∼ f i − 1 g_{i-1}sim f_{i-1} gi−1​∼fi−1​ 中的空位中选择一个,并用掉一个空位。
    #include
    using namespace std;
    #define rep(i, a, b) for(int i = (a); i <= (b); i++)
    #define per(i, a, b) for(int i = (a); i >= (b); i--)
    #define ll long long
    #define db double
    #define VI vector
    #define PII pair
    #define Pi 3.141592653589793
    const int INF = 0x7fffffff;
    const int N = 2e6 + 200;
    const db eps = 1e-10;
    const ll mod = 1e9 + 7;
    int cas, n, ok;
    ll ans, h[N], midempty;
    int main(){
        ios::sync_with_stdio(0),cin.tie(0);
        cin >> cas;
        while(cas--){
            cin >> n;
            ok = 1;
            rep(i, 1, n){
                cin >> h[i];
                //无解情况
                if(i == 1 && h[i] != 0) ok = 0;
                if(i > 1 && h[i] == 0) ok = 0;  //a 为一个排列
                if(h[i] >= n) ok = 0;
                if(h[i - 1] > h[i]) ok = 0;
            }
            if(!ok){
                cout << 0 << endl;   //不要轻易用puts("0") 不知道为什么会错!!!
                continue;
            }
            ans = 1, midempty = 0;
            rep(i, 2, n){
                if(h[i] == h[i - 1]){
                    (ans *= midempty) %= mod;
                    midempty--;
                }
                else{ // h[i] > h[i - 1]
                    (ans *= 2) %= mod;
                    midempty += h[i] - h[i - 1] - 1;
                }
            }
            cout << ans << endl;
        }
    }
    
    
2020 上海 D. Walker
  • Walker

  • 思路:

    • 首先 calc 这个函数绝妙,省去许多情况的讨论。

    • 其次,分为三种情况:

      1. 一个人速度特别快,自己就走完全程即可。
      2. 两个人速度差距不大,但是速度慢的离自己临近端点较远,两个人只需要走到对面端点即可。
      3. 两个人分别负责自己的区间,争取同时完成(但不能强求),两个区间交点便应该在 p1 和 p2 之间,二分查找最优答案即可。

      我们一开始想到二分,但是写的复杂了许多,还没有用那个函数,越写越臃肿,思路就更乱了。

    #include
    using namespace std;
    #define rep(i, a, b) for(int i = (a); i <= (b); i++)
    #define per(i, a, b) for(int i = (a); i >= (b); i--)
    #define ll long long
    #define db double
    #define VI vector
    #define PII pair
    const db Pi = 3.141592653589793;
    const int INF = 0x7fffffff;
    const int N = 1e5 + 5;
    const db eps = 1e-10;
    int cas;
    db p1, p2, v1, v2, n, ans;
    db calc(db l, db r, db v){  //左边距离为l,右边距离为r时,速度为v所需要的时间
        return (min(l, r) * 2.0 + max(l, r)) / v;
    }
    int main(){
        cin >> cas;
        while(cas--){
            scanf("%lf%lf%lf%lf%lf", &n, &p1, &v1, &p2, &v2);
            if(p1 > p2){
                swap(p1, p2);
                swap(v1, v2);
            }
            //只有一个走
            ans = min(calc(p1, n - p1, v1), calc(p2, n - p2, v2));
            //交叉走
            ans = min(ans, max((n - p1) / v1, p2 / v2));
            //两人各走左右两边
            db l = p1, r = p2, mid;
            while(r - l > eps){
                mid = (l + r) / 2;
                if(calc(p1, mid - p1, v1) > calc(p2 - mid, n - p2, v2)) r = mid;
                else l = mid;
            }
            ans = min(ans, max(calc(p1, l - p1, v1), calc(p2 - l, n - p2, v2)));
            printf("%.9lfn", ans);
        }
    }
    
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/487909.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号