zoukankan      html  css  js  c++  java
  • 2020牛客国庆集训派对day1

    题目来源: ICPC Central Europe Regional Contest 2019

    链接

    A. AAB

    找最长后缀回文串

    思路:

    KMP,正串和逆串匹配

    #include<bits/stdc++.h>
    using namespace std;
    
    string s,p;
    int n;
    const int maxn = 4e5+10;
    int nxt[maxn];
    int main(){
        ios::sync_with_stdio(0);
        cin >> n;
        cin >> s;
        p = s;
        reverse(p.begin(),p.end());
        nxt[0] = -1;
    	int j = 0, k = -1;
        int m = n;
    	while (j < m) {
    		if (k == -1 or s[j] == s[k]) nxt[++j] = ++k;
    		else k = nxt[k];
    	}
        int i = 0;
    	j = 0;
        int ans = 1;
    	while (i < n) {
    		if (j == -1 or s[i] == p[j]) {
    			i++; j++;
    			if(i == n){
                    ans = max(ans,j);
                }
    		}
    		else {
    			j = nxt[j];
    		}
    	}
    	cout << n - ans << endl;
        
    }
    

    也可以用马拉车,注意要开两倍空间

    #include<bits/stdc++.h>
    using namespace std;
    
    string s,t;
    int n;
    const int maxn = 1e6+10;
    int p[maxn];
    int main(){
        ios::sync_with_stdio(0);
        cin >> n;
        cin >> s;
        t = "$";
        for(int i = 0;i < n;i++){
            t += "#" + s.substr(i,1);
        }
        t += "#@";
        n = t.length();
        int ans = 1;
        int c = 0,r = 0;
        for(int i = 1;i < n - 1;i++){
            p[i] = i < r ? min(p[2*c-i],r-i) : 1;
            while(t[i-p[i]] == t[i+p[i]])p[i]++;
            if(i+p[i] > r){
                r = p[i] + i;
                c = i;
            }
            if( (i - p[i] + 1) / 2 + p[i] - 1 == s.size()){
                ans = max(ans,p[i]-1);
            }
        }
        cout << s.size() - ans << endl;
    }
    

    C. Bob in Wonderland

    拆链,思维题

    队友的代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    //typedef __int128 lll;
    #define print(i) cout << "debug: " << i << endl
    #define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
    #define mem(a, b) memset(a, b, sizeof(a))
    const ll mod = 1e9 + 7;
    const int maxn = 2e6;
    const int inf = 0x3f3f3f3f;
    int d[maxn];
    
    int main()
    {
        int n; cin >> n;
    	for(int i = 1; i < n; i++)
    	{
    		int a, b; scanf("%d%d", &a, &b);
    		d[a]++, d[b]++;
    	}
    	int res = 0;
    	for(int i = 1; i <= n; i++)
    		if(d[i] >= 3)
    			res += (d[i] - 2);
    	cout << res << endl;
    }
    

    D. Deep800080

    计算几何

    转换成线段的交,注意排序规则

    不知道为什么用 %d 输入再强制类型转换过不去??一直卡 98.94%

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 3e5 + 10;
    int n;
    double r, a, b;
    const double pi = acos(-1.0);
    const double eps = 1e-8;
    
    int sgn(double x) {
    	if (fabs(x) < eps)return 0;
    	if (x > 0)return 1;
    	else return -1;
    }
    struct Point {
    	double x, y;
    	int val;
    	Point() {}
    	Point(double _x, double _y) {
    		x = _x;
    		y = _y;
    		val = 0;
    	}
    	double distance(Point p) {
    		return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    	}
    	bool operator <(const Point& b)const {
    		//左下小
    		if (sgn(x - b.x) == 0) {
    			if (sgn(y - b.y) == 0) {
    				return val > b.val;
    			}
    			return y < b.y;
    		}
    		return x < b.x;
    	}
    	Point operator +(const Point& b)const {
    		return Point{ x + b.x, y + b.y };
    	}
    	Point operator *(const double& k)const {
    		return Point{ x * k, y * k };
    
    	}
    	Point operator /(const double& k)const {
    		return Point{ x / k, y / k };
    
    	}
    	Point operator -(const Point& b)const {
    		return Point{ x - b.x,y - b.y };
    	}
    	double operator *(const Point& b)const {
    		return x * b.x + y * b.y;
    	}
    	double len() {
    		return hypot(x, y);
    	}
    	double len2() {
    		return x * x + y * y;
    	}
    };
    
    struct Line {
    	Point s, e;
    	Line() {}
    	Line(Point _s, Point _e) {
    		s = _s;
    		e = _e;
    	}
    	Point lineProg(Point p) {
    		return s + (((e - s) * ((e - s) * (p - s))) / ((e - s).len2()));
    	}
    	double angle() {
    		double k = atan2(e.y - s.y, e.x - s.x);
    		if (sgn(k) < 0) k += pi;
    		if (sgn(k - pi) == 0) k -= pi;
    		return k;
    	}
    };
    vector<Point>A;
    int main() {
        //scanf("%d%d%d%d") ???? %d 输入再强转就wa????
    	scanf("%d%lf%lf%lf", &n, &r, &a, &b);
    	Line l = Line(Point(0, 0), Point(a, b));
    	double angle = l.angle();
    	for (int i = 0; i < n; i++) {
    		double x, y;
    		scanf("%lf%lf", &x, &y);
    		Point u = l.lineProg(Point{ x,y });
    		double d = u.distance(Point{ x,y });
    		if (sgn(d - r) > 0)continue;
    		double t = sqrt(r * r - d * d);
    		Point a = Point{ u.x + cos(angle) * t,u.y + sin(angle) * t };
    		Point b = Point{ u.x - cos(angle) * t,u.y - sin(angle) * t };
    		if (a < b) { a.val = 1; b.val = -1; }
    
            else { a.val = -1; b.val = 1; }
    		A.push_back(a);
    		A.push_back(b);
    	}
    	sort(A.begin(), A.end());
    	int ans = 0, sum = 0;
    	for (Point x : A) {
    		sum += x.val;
    		ans = max(ans, sum);
    	}
    	printf("%d
    ", ans);
    }
    

    E. Zeldain Garden

    (d(n)) 前缀和,不用筛,简单分块

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    ll solve(ll n){
        ll ans = 0;
        for(ll l = 1,r;l <= n;l = r + 1){
            r = n / (n / l);
            ans += (r-l+1)*(n/l);
        }
        return ans;
    }
    int main(){
        ll x,y;
        cin >> x >> y;
        cout << solve(y) - solve(x-1) << endl;
    }
    

    F. Light Emitting Hindenburg

    二进制,简单模拟

    题目的锅,是 (2^{30-L}) ,其实就是二进制表示

    其实就是 (n) 个数里面挑 (m) 个数,使得他们相与(&)最大

    从高位往低位挑就可以

    #include<bits/stdc++.h>
    using namespace std;
    
    
    int n,k,x;
    const int N = 2e5+10;
    int bt[40][N];
    int vis[40][N];
    
    int main(){
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;i++){
            scanf("%d",&x);
            for(int j = 0;j < 31;j++){
                if(x & (1 << j)){
                    bt[j][i] = 1;
                }
            }
        }
        int ans = 0;
        int t = 1;
        for(int j = 30;j >= 0;j--){
            int cnt = 0;
            for(int i = n;i >= 1;i--){
                if(vis[j+1][i] == t - 1 and bt[j][i] == 1){
                    cnt++;
                }
                vis[j][i] = vis[j+1][i];
            }
            if(cnt >= k){
                ans += (1<<j);
             
                for(int i = n;i >= 1;i--){
                    if(vis[j+1][i] == t - 1 and bt[j][i] == 1){
                        vis[j][i] = t;
                    }
                }
                t++;
            }
        }
        printf("%d
    ",ans);
    }
    

    G. K == S

    AC自动机 ,矩阵快速幂

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    
    const int N = 7e5 + 10;
    queue<int>q;
    const int mod = 1e9 + 7;
    
    struct Mat {
    	int m[500][500], n;
    	Mat(int _n,int v) {
    		n = _n;
    		memset(m, 0, sizeof m);
    		for (int i = 0; i < n; i++)m[i][i] = v;
    	}
    	Mat operator *(const Mat& b)const {
    		Mat res = Mat(b.n,0);
    		int n = b.n;
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < n; j++) {
    				for (int k = 0; k < n; k++) {
    					res.m[i][j] = (res.m[i][j] + m[i][k] * b.m[k][j]) % mod;
    				}
    			}
    		}
    		return res;
    	}
    };
    struct {
    	int c[N][26], fail[N], val[N], cnt;
    	void insert(char* s) {
    		int len = strlen(s); int now = 0;
    		for (int i = 0; i < len; i++) {
    			int v = s[i] - 'a';
    			if (!c[now][v])c[now][v] = ++cnt;
    			now = c[now][v];
    		}
    		//val[now]++;
            val[now] = 1;
    	}
    	void getFail() {
    		for (int i = 0; i < 26; i++) {
    			if (c[0][i])fail[c[0][i]] = 0, q.push(c[0][i]);
    			//***
    			else c[0][i] = 0;
    		}
    		
    		
    		while (!q.empty()) {
    			int u = q.front(); q.pop();
    
    			//***
    			if (val[fail[u]] == 1) {
    				val[u] = 1;
    			}
    
    			for (int i = 0; i < 26; i++) {
    				if (c[u][i]) {
    					fail[c[u][i]] = c[fail[u]][i];
    					q.push(c[u][i]);
    				}
    				else c[u][i] = c[fail[u]][i];
    			}
    		}
    	}
    	int query(char* s) {
    		int len = strlen(s); int now = 0, ans = 0;
    		for (int i = 0; i < len; i++) {
    			now = c[now][s[i] - 'a'];
    			for (int t = now; t && val[t] != -1; t = fail[t]) {
    				ans += val[t];
    				val[t] = -1;
    			}
    		}
    		return ans;
    	}
    	Mat getMat() {
            //这里 cnt 也能过,但是上面的POJ会wa,这里数据的问题,应该是cnt+1
    		Mat res = Mat(cnt + 1, 0);
    		for (int i = 0; i <= cnt; i++) {
    			for (int j = 0; j < 26; j++) {
    				if (!val[c[i][j]]) {
    					res.m[i][c[i][j]]++;
    				}
    			}
    		}
    		return res;
    	}
    
    }Ac;
    
    Mat qpow(Mat a, int p) {
    	Mat res = Mat(a.n, 1);
    	while (p) {
    		if (p & 1) res = a * res;
    		a = a * a;
    		p >>= 1;
    	}
    	return res;
    }
    
    int n;
    char p[N];
    
    signed main() {
    	int n, m, x;
    	scanf("%lld%lld", &n, &m);
    	for (int i = 0; i < m; i++) {
    		scanf("%lld%s", &x, p);
    		Ac.insert(p);
    	}
    	Ac.getFail();
    	Mat mat = Ac.getMat();
    	mat = qpow(mat, n);
    
    	int ans = 0;
    	for (int i = 0; i < mat.n; i++) {
    		ans = (ans + mat.m[0][i]) % mod;
    	}
    	printf("%lld
    ", ans);
    }
    

    H. Ponk Warshall

    拆环

    这份dfs的代码MLE 了,就改成了暴力拆

    /*
    * Status: MLE
    */
    #include<bits/stdc++.h>
    using namespace std;
    
    map<char, int>mp;
    int G[5][5];
    int out[5];
    const int N = 1e6+10;
    char s[N],t[N];
    int ans;
    
    void dfs(int u, int len, int target) {
    	if (u == target and len != -1) {
    		ans += len;
    		return;
    	}
    	for (int i = 1; i <= 4; i++) {
    		if (G[u][i] > 0) {
    			dfs(i, len + 1, target);
    			G[u][i]--;
    			out[u]--;
    		}
    	}
    }
    int main() {
    	mp['A'] = 1; mp['C'] = 2;
    	mp['G'] = 3; mp['T'] = 4;
    
    	scanf("%s",s);
        scanf("%s",t);
    	int n = strlen(s);
    	for (int i = 0; i < n; i++) {
    		G[mp[s[i]]][mp[t[i]]]++;
    		out[mp[s[i]]]++;
    	}
    
    	for (int i = 1; i <= 4; i++) {
    		while (out[i] != 0) {
    			dfs(i, -1, i);
    		}
    	}
    	printf("%d
    ",ans);
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    
    map<char, int>mp;
    int G[5][5];
    int out[5];
    const int N = 1e6 + 10;
    char s[N], t[N];
    int ans;
    
    int main() {
    	mp['A'] = 1; mp['C'] = 2;
    	mp['G'] = 3; mp['T'] = 4;
    
    	scanf("%s", s);
    	scanf("%s", t);
    	int n = strlen(s);
    	for (int i = 0; i < n; i++) {
    		G[mp[s[i]]][mp[t[i]]]++;
    	}
    	for (int i = 1; i <= 4; i++) {
    		while (G[i][i])G[i][i]--;
    	}
    
    	for (int i = 1; i <= 4; i++) {
    		for (int j = i + 1; j <= 4; j++) {
    			while (G[i][j] and G[j][i]) {
    				G[i][j]--; G[j][i]--;
    				ans++;
    			}
    		}
    	}
    
    	for (int i = 1; i <= 4; i++) {
    		for (int j = 1; j <= 4; j++) {
    			for (int k = 1; k <= 4; k++) {
    				if (i == j or j == k or k == i)continue;
    				while (G[i][j] and G[j][k] and G[k][i]) {
    					G[i][j]--; G[j][k]--; G[k][i]--;
    					ans += 2;
    				}
    			}
    		}
    	}
    	for (int i = 1; i <= 4; i++) {
    		for (int j = 1; j <= 4; j++) {
    			if (i == j)continue;
    			for (int k = 1; k <= 4; k++) {
    				if (k == i or k == j)continue;
    				for (int u = 1; u <= 4; u++) {
    					if (u == i or u == j or u == k)continue;
    					while (G[i][j] and G[j][k] and G[k][u] and G[u][i]) {
    						G[i][j]--; G[j][k]--; G[k][u]--; G[u][i]--;
    						ans += 3;
    					}
    				}
    			}
    		}
    	}
    	printf("%d
    ", ans);
    }
    

    J. The Bugs

    稍微复杂一点的模拟+RMQ

  • 相关阅读:
    bootstrap 兼容 IE8
    在IE8的基础上安装IE11
    前台
    dll 库文件下载地址
    年轻
    linux 异常
    Navicat断网时连不上数据库
    jQuery
    破解版 Teamver 安装
    mysql
  • 原文地址:https://www.cnblogs.com/sduwh/p/13760366.html
Copyright © 2011-2022 走看看