杭电第八场

杭电第八场

Problem C:Clockwise or Counterclockwise

思路:

画图可知,当C点在向量AB的右边时,图形为顺时针,则向量AB与向量AC的叉乘的值应小于0。

代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
struct Point{
    ll x;
    ll y;
}point[10];

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int T; cin >> T;
    while(T--){
        cin >> point[1].x >> point[1].y >> point[2].x >> point[2].y >> point[3].x >> point[3].y;
        point[4].x = point[2].x - point[1].x;
        point[4].y = point[2].y - point[1].y;
        point[5].x = point[3].x - point[1].x;
        point[5].y = point[3].y - point[1].y;
        if(point[4].x * point[5].y - point[4].y * point[5].x < 0)
            cout << "Clockwise\n";
        else cout << "Counterclockwise\n";
    }
    return 0;
}

Problem F:Fluctuation Limit

思路:

当每输入一次范围时,只需要达到输入的范围的最小值大于等于上一次输入的最小值-k(即li - k),输入的范围的最大值小于等于上一次输入的最大值+k(即ri + k)即可,若存在没有达到此条件的范围,则输出“NO”,反之输出“YES”,可能的值可随机输出每个达标范围的任意值(这里为了简化编程我们输出的为最小值)

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;
int l[N], r[N];
int main (){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int T; cin >> T;
    while(T--){
        int n, k; cin >> n >> k;
        for(int i = 1; i <= n; i++) cin >> l[i] >> r[i];
        for(int i = 1; i < n; i++){
            l[i + 1] = max(l[i + 1], l[i] - k);
            r[i + 1] = min(r[i + 1], r[i] + k);
        }
        for(int i = n; i > 1; i--){
            l[i - 1] = max(l[i - 1], l[i] - k);
            r[i - 1] = min(r[i - 1],r[i] + k);
        }
        bool flag = true;
        for(int i = 1; i <= n; i++){
            if(l[i] > r[i]) flag = false;
        }
        if(flag){
            cout << "YES\n";
            for(int i = 1; i <= n; i++){
                cout << l[i];
                if(i != n) cout << " ";
                else cout << endl;
            }
        }
        else cout << "NO\n";
    }
    return 0;
}

Problem I:Isomorphic Strings

思路:

题意为,将字符串s平均分割为k块(其中strlen(s)% k == 0 && k > 1)是得k个子字符串相互循环同构。假设s中某元素出现了x次,那么关于循环同构,此字符串最多被分为x个等长度相邻字串,由此可知,字符串满足循环同构必须满足s可被分段的段数为出现次数最少的元素的次数。我们可在此次数的条件下进行枚举其中n % 次数 其值为 0 才满足条件,否则此枚举不满足,应跳过。如果所有枚举都不满足,则s字符串不满足题意,输出“No”,若存在一个满足的枚举值,则输出“Yes”。

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int mac = 5e6 + 10;
const int mod = 7e6 + 61;
const int base = 29;

char s[mac];
int nb[30];
int vis[mac << 1];
ll pw[mac];
int cnt = 0;
int check(int n, int len){
    cnt ++;
    ll p = 0, ps = 0;
    for(int i = 0; i < len; i++) p = (p * base + s[i] - 'a' + 1) % mod;
    vis[p] = cnt;
    int tp = s[0] - 'a' + 1, num = 1;
    for(int i = 1; i < len; i++){
        ll pp = ((p - (1ll * tp * pw[len - 1] % mod) + mod) % mod * base % mod + tp) % mod;
        vis[pp] = cnt;
        p = pp;
        tp = s[num++] - 'a' + 1;
    }
    for(int i = 1; i < n / len; i++){
        ll use = 0, uses = 0;
        for(int j = i * len; j < (i + 1) * len; j++) use = (use * base + s[j] - 'a' + 1) % mod;
        if(vis[use] != cnt) return 0;
    }
    return 1;
}
int main (){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    int T; cin >> T;
    pw[0] = 1;
    for(int i = 1; i < mac - 5; i++) pw[i] = pw[i - 1] * base % mod;
    while(T--){
        int n; cin >> n >> s; 
        int mk = 0;
        int mi = 1 << 30;
        memset(nb, 0, sizeof(nb));
        for(int i = 0; i < n; i++) nb[s[i] - 'a'] ++;
        for(int i = 0; i < 26; i++){
            if(nb[i]) mi = min(mi, nb[i]);
        }
        if(mi == 1) {cout << "No\n"; continue;}
        for(int i = 1; 1ll * i * i <= mi; i++){
            if(mi % 1) continue;
            int ok = 0;
            if(i > 1 && n % i == 0) ok = check(n, n / i);
            if(ok) {mk = 1; break; }
            int fac = mi / i;
            if(fac == i) continue;
            if(fac == 1) continue;
            if(n % fac) continue;
            ok = check(n, n / fac);
            if(ok) {mk = 1; break; }
        }
        if(mk) cout << "Yes\n";
        else cout << "No\n";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值