zoukankan      html  css  js  c++  java
  • Codeforces Round #341 (Div. 2)

    在家都变的懒惰了,好久没写题解了,补补CF

    模拟 A - Wet Shark and Odd and Even

    #include <bits/stdc++.h>
    
    typedef long long ll;
    const int N = 1e5 + 5;
    const int INF = 0x3f3f3f3f;
    
    int main(void)	{
    	std::vector<int> vec;
    	int n;	scanf ("%d", &n);
    	ll sum = 0;
    	for (int x, i=1; i<=n; ++i)	{
    		scanf ("%d", &x);
    		sum += x;
    		if (x & 1)	vec.push_back (x);
    	}
    	std::sort (vec.begin (), vec.end ());
    	int sz = vec.size ();
    	if (sz > 0 && (sz & 1))	sum -= vec[0];
    	printf ("%I64d
    ", sum);
    
    	return 0;
    }
    

    暴力 B - Wet Shark and Bishops

    开始想错了,当成斜率相等的。还好1000范围不大,统计矩阵每条对角线上的个数加点小优化就过了,代码丑。。。

    #include <bits/stdc++.h>
    
    typedef long long ll;
    const int N = 2e5 + 5;
    bool vis[2][1005][1005];
    int b[1005][1005];
    std::pair<int, int> a[N];
    
    ll cal(int x)	{
    	return 1ll * x * (x - 1) / 2;
    }
    int get_num1(int x, int y)	{
    	int xx = x, yy = y;
    	int ret = 0;
    	while (xx >= 1 && yy >= 1)	{
    		if (b[xx][yy])	ret++, vis[1][xx][yy] = true;
    		xx--;	yy--;
    	}
    	xx = x + 1, yy = y + 1;
    	while (xx <= 1000 && yy <= 1000)	{
    		if (b[xx][yy])	ret++, vis[1][xx][yy] = true;
    		xx++;	yy++;
    	}
    	return ret;
    }
    
    int get_num0(int x, int y)	{
    	int xx = x, yy = y;
    	int ret = 0;
    	while (xx <= 1000 && yy >= 1)	{
    		if (b[xx][yy])	ret++, vis[0][xx][yy] = true;
    		xx++;	yy--;
    	}
    	xx = x - 1, yy = y + 1;
    	while (xx >= 1 && yy <= 1000)	{
    		if (b[xx][yy])	ret++, vis[0][xx][yy] = true;
    		xx--;	yy++;
    	}
    	return ret;
    }
    
    int main(void)	{
    	int n;	scanf ("%d", &n);
    	for (int i=0; i<n; ++i)	{
    		scanf ("%d%d", &a[i].first, &a[i].second);
    		b[a[i].first][a[i].second] = 1;
    	}
    	ll ans = 0;
    	for (int i=0; i<n; ++i)	{
    		int x = a[i].first, y = a[i].second;
    		if (!vis[0][x][y])	{
    			ans += cal (get_num0 (x, y));
    			vis[0][x][y] = true;
    		}
    		if (!vis[1][x][y])	{
    			ans += cal (get_num1 (x, y));
    			vis[1][x][y] = true;
    		}
    	}
    	printf ("%I64d
    ", ans);
    
    	return 0;
    }
    

    期望 C - Wet Shark and Flowers

    E = sum (1000 * 乘积是p的倍数的概率)

    #include <bits/stdc++.h>
    
    typedef long long ll;
    const int N = 1e5 + 5;
    const int EPS = 1e-8;
    int l[N], r[N];
    double pos[N];
    
    int main(void)	{
    	int n, p;	scanf ("%d%d", &n, &p);
    	for (int i=1; i<=n; ++i)	{
    		scanf ("%d%d", &l[i], &r[i]);
    		pos[i] = 1.0 * (r[i] / p - ((l[i]-1) / p)) / (r[i] - l[i] + 1);
    	}
    	l[0] = l[n], r[0] = r[n], pos[0] = pos[n];
    	double ans = 0;
    	for (int i=0; i<=n; ++i)	{
    		if (i < n)	ans += pos[i] * 1.0 + (1.0 - pos[i]) * pos[i+1];
    		if (i > 0)	ans += pos[i] * 1.0 + (1.0 - pos[i]) * pos[i-1];
    	}
    	ans *= 1000;
    	printf ("%.8f
    ", ans);
    
    	return 0;
    }
    

    数学(浮点) D - Rat Kwesh and Cheese

    都取log,用long double,精度逆天!powl (): pow的long double版

    C语言里对float类型数据的表示范围为-3.4*10^38~+3.4*10^38。double为-1.7*10^-308~1.7*10^308,long double为-1.2*10^-4932~1.2*10^4932.

    类型

    比特(位)数

    有效数字

    数值范围

    float

    32

    6~7

    -3.4*10^38~+3.4*10^38

    double

    64

    15~16

    -1.7*10^-308~1.7*10^308

    long double

    128/

    18~19

    -1.2*10^-4932~1.2*10^4932

     

     

     

     

     

     

    究竟如何计算该范围,分析如下:

    对于单精度浮点数(float)来说,符号位一位,指数位8位,尾数23位。指数能够表示的指数范围为-128~127。尾数为23位。

    #include <bits/stdc++.h>
    
    std::string ans[12] = {
    "x^y^z", "x^z^y", "(x^y)^z", "(x^z)^y", "y^x^z", "y^z^x",
    "(y^x)^z", "(y^z)^x", "z^x^y", "z^y^x", "(z^x)^y", "(z^y)^x"
    };
    
    typedef long double ldouble;
    const double EPS = 1e-10;
    ldouble best;
    int id;
    
    bool better(ldouble val)	{
    	if (fabs (val - best) < EPS)	return false;
    	else if (best < val)	{
    		best = val;
    		return true;
    	}
    	return false;
    }
    
    void try2(ldouble x, ldouble y, ldouble z, int pos)	{
    	//(x ^ y) ^ z
    	ldouble val = z * y * log (x);
    	if (better (val))	id = pos;
    }
    
    void try1(ldouble x, ldouble y, ldouble z, int pos)	{
    	//x ^ y ^ z
    	ldouble val = powl (y, z) * log (x);
    	if (better (val))	id = pos;
    }
    
    int main(void)	{
    	ldouble x, y, z;	std::cin >> x >> y >> z;
    	best = -1e12;	id = -1;
    	try1 (x, y, z, 0);
    	try1 (x, z, y, 1);
    	try2 (x, y, z, 2);
    	try2 (x, z, y, 3);
    	try1 (y, x, z, 4);
    	try1 (y, z, x, 5);
    	try2 (y, x, z, 6);
    	try2 (y, z, x, 7);
    	try1 (z, x, y, 8);
    	try1 (z, y, x, 9);
    	try2 (z, x, y, 10);
    	try2 (z, y, x, 11);
    	std::cout << ans[id] << '
    ';
    
    	return 0;
    }
    

     

    数位DP(矩阵快速幂优化) E - Wet Shark and Blocks

    题意:b组相同的n个数字,每组选择一个数字合并起来%x == k的方案数。

    分析:dp思路,dp[i][(j*10+t)%x] += dp[i-1][j]。但是b太大了选择用矩阵快速幂优化,构造矩阵m[i][j]表示从i到j的方案数,答案就是m[0][k],那么base矩阵就是小于x的某个数字转移到根据给出n个数字转移到另一个数字y的方案数。

    UPD:

    寒假排位赛出了这题,又不会做。

    构造x*x大小的矩阵,m[i][j]表示从i(%x)到j(%x)的方案数,状态转移用矩阵乘法:i->j1,j2,j3...->k => i->k

     

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef vector<ll> Vec;
    typedef vector<Vec> Mat;
    const int N = 5e4 + 5;
    const int MOD = 1e9 + 7;
    int cnt[10];
    int n, b, k, x;
    
    void add_mod(ll &a, ll b) {
        a += b;
        if (a >= MOD) a -= MOD;
    }
    
    Mat matrix_mul(const Mat &A, const Mat &B) {
        Mat ret(A.size(), Vec(B[0].size()));
        for (int i=0; i<A.size(); ++i)
            for (int j=0; j<A[0].size(); ++j) if (A[i][j])
                for (int k=0; k<B[0].size(); ++k) if (B[j][k])
                    add_mod(ret[i][k], A[i][j]*B[j][k]%MOD);
        return ret;
    }
    
    Mat matrix_pow(Mat X, int n) {
        Mat ret(X.size(), Vec(X.size()));
        for (int i=0; i<X.size(); ++i) ret[i][i] = 1;
        for (; n; n>>=1) {
            if (n & 1) ret = matrix_mul(ret, X);
            X = matrix_mul(X, X);
        }
        return ret;
    }
    
    int main() {
        scanf("%d%d%d%d", &n, &b, &k, &x);
        for (int i=1; i<=n; ++i) {
            int d;
            scanf("%d", &d);
            cnt[d]++;
        }
        Mat ans(100, Vec(100));
        for (int i=0; i<x; ++i) {
            for (int j=1; j<=9; ++j) {
                ans[i][(i*10+j)%x] += cnt[j];
            }
        }
        ans = matrix_pow(ans, b);
        printf("%I64d
    ", ans[0][k]);
        return 0;
    }

     

      

     

    编译人生,运行世界!
  • 相关阅读:
    对象池使用时要注意几点
    Flash3D学习计划(一)——3D渲染的一般管线流程
    714. Best Time to Buy and Sell Stock with Transaction Fee
    712. Minimum ASCII Delete Sum for Two Strings
    647. Palindromic Substrings(马拉车算法)
    413. Arithmetic Slices
    877. Stone Game
    338. Counting Bits
    303. Range Sum Query
    198. House Robber
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5176114.html
Copyright © 2011-2022 走看看