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

    Codeforces Round #538 (Div. 2) (CF1114)

      今天昨天晚上的cf打的非常惨(仅代表淮中最低水平

      先是一路缓慢地才A掉B,C,然后就开始杠D。于是写出了一个O(n^2)的线性dp,然后就wa6,调到结束。结束后发现完全看漏了两句话。噢,起始点!!!

      好吧然后算算自己有可能这一场要变成+0,反正在0左右。
    结束后开始然后开始写D,顺便思考F。结果写完D发现A怎么fst了,然后。。。因为习惯于对相似的语句复制粘贴,有些东西没有改——三句话都在 -a!!!(这个还能过pt?

      好吧想完F以后又顺便看了一下。发现怎么B也fst了???发现好像忘了考虑相同的数的问题。。。

      还好C没有fst。所以大概不多不少,可以把上一场涨的分数给抵掉。

      也是wph学长说的好,这些都是用血换来的教训啊。(但是看错题真的不应该,这是在NOIP就犯过的错啊。


    A. Got Any Grapes?

      这种题目直接做,显然是先尽量供给Andrew,然后是Dmitry,最后是Michal。

      希望大家不要犯我犯过的错误。(以后记得复制粘贴相似内容的时候注意修改全所有该修改的东西啊)

    int x, y, z, a, b, c;
    
    inline void End() {puts("NO"); exit(0);}
    
    int main() {
    	read(a), read(b), read(c);
    	read(x), read(y), read(z);
    	if (x < a) End(); else x -= a;
    	y += x;
    	if (y < b) End(); else y -= b;
    	z += y;
    	if (z < c) End(); else z -= c;
    	puts("YES");
    }
    

    B. Yet Another Array Partitioning Task

      CF上的B题一般都是大胆猜结论题目。

      直接猜结论: 一定可以选齐前 (m cdot k) 大的数。然后分的时候只要凑齐 (m) 个在前 (m cdot k) 大的数中的数,就可以切一块。

      注意一下(也是我fst的原因),如果前 (m cdot k) 中最小的数没有被选全的话,那么分的时候要注意判断一下那个数已经选了多少个,不够选了就不要把它算上去。

    const int N = 2e5 + 7;
    int n, m, k, p, a[N], b[N];
    ll ans;
    std::map<int, int> mp;
    
    int main() {
    	read(n), read(m), read(k); p = m * k; --k;
    	for (int i = 1; i <= n; ++i) read(a[i]), b[i] = a[i];
    	std::sort(b + 1, b + n + 1);
    	for (int i = n - p + 1; i <= n; ++i) ans += b[i], mp[b[i]]++;
    	printf("%I64d
    ", ans);
    	for (int i = 1, cnt = 0; i <= n; ++i) {
    		if (mp.count(a[i]) && mp[a[i]]) ++cnt, --mp[a[i]];
    		if (cnt == m) --k, printf("%d%c", i, " 
    "[k == 0]), cnt = 0;
    		if (!k) return 0;
    	}
    }
    

    C. Trailing Loves (or L'oeufs?)

      在 (b) 进制下末尾有 (k) 个0,那么说明

    [quad b ^ k | n! ]

      于是我们把 (b) 分解质因数

    [(p_1^{k_1} cdot p_2^{k_2} cdot cdots) ^k | n! ]

      于是我们发现

    [k = min{log_{p_1} n!, log_{p_2}{n!}, cdots } ]

      至于说 (log_p{n!}) 怎么求,这个应该是普及组知识了。

    [log_p n!= sum_{i = 1} lfloor frac n {p ^ i} floor ]

    const int N = 1e6 + 7;
    ll n, m, ans = 0x7fffffffffffffff;
    int np[N], p[N], prt, cnt[N];
    
    inline void Make_Prime(int n ){
    	np[0] = np[1] = 1;
    	for (int i = 2; i <= n; ++i) {
    		if (!np[i]) p[++prt] = i;
    		for (int j = 1; j <= prt && i * p[j] <= n; ++j) {
    			np[i * p[j]] = 1;
    			if (i % p[j]) break;
    		}
    	}
    }
    
    inline ll GetNum(ll n, ll x) {
    	ll ans = 0;
    	while (n) ans += n /= x;
    	return ans;
    }
    
    int main() {
    	read(n), read(m);
    	Make_Prime(sqrt(m));
    	ll hkk = m;
    	for (int i = 1; i <= prt; ++i)
    		while (hkk % p[i] == 0) hkk /= p[i], ++cnt[i];
    	for (int i = 1; i <= prt; ++i) if (cnt[i]) SMIN(ans, GetNum(n, p[i]) / cnt[i]);
    	if (hkk > 1) SMIN(ans, GetNum(n, hkk));
    	printf("%I64d
    ", ans);
    }
    

    D. Flood Fill

      这道题一开始没看见起始方块这个东西,一直wa6。

      如果有起始点,那就是区间dp模板了。

      设 (dp[i][j]) 表示 (i..j) 的这段区间全部化成一种颜色的代价。

    [dp[i][j] = left{ egin{align*} &dp[i+1][j-1] &&c[i] = c[j]\ &min{dp[i][j-1], dp[i][j+1]} + 1 &&c[i] eq c[j] end{align*} ight. ]

    const int N = 5000 + 7;
    const int INF = 0x3f3f3f3f;
    
    int n, m, c[N], dp[N][N];
    
    int main() {
    	read(n);
    	for (int i = 1; i <= n; ++i) read(c[i]), SMAX(m, c[i]);
    	n = std::unique(c + 1, c + n +1) - c - 1;
    	for (int i = n; i; --i)
    		for (int j = i + 1; j <= n; ++j)
    			if(c[i] == c[j]) dp[i][j] = dp[i + 1][j - 1] + 1;
    			else dp[i][j] = std::min(dp[i][j - 1], dp[i + 1][j]) + 1;
    	printf("%d
    ", dp[1][n]);
    }
    

    E. Arithmetic Progression

      交互题娱乐身心。

      显然我们一个二分就可以很开心地求出最大值。

      然后我们就可发现,任意两个数的差都应该是公差的倍数。于是我们多随机一些位置,因为前面二分过,所以后面最多问30次左右(当然不能直接问前30个,防止毒瘤会卡),把位置上的值与最大值的差算出来,那么公差一定是它们的约数,有很大的概率是 (gcd)

      不会证明正确率。

    const int N = 1e6 + 7;
    int n, L, R, stp, used[N];
    
    int main() {
    	read(n); srand(time(0));
    	int l = 0, r = 1e9;
    	while (l < r) {
    		int mid = (l + r) >> 1, get;
    		printf("> %d
    ", mid); fflush(stdout);
    		read(get);
    		if(get) l = mid + 1;
    		else r = mid;
    	}
    	R = l;
    	for (int i = 1, get = 0; i <= 30 && i <= n; ++i) {
    		int pos = rand() % n + 1;
    		while(used[pos]) pos = rand() % n + 1;
    		used[pos] = 1;
    		printf("? %d
    ", pos); fflush(stdout);
    		read(get);
    		stp = std::__gcd(stp, R - get);
    	}
    	printf("! %d %d
    ", R - (n - 1) * stp, stp);
    	fflush(stdout);
    }
    

    F. Please, another Queries on Array?

      回顾一下欧拉函数的公式。

    [varphi(n) = n sum_{p ext{是}n ext{质因数}} 1-frac1p ]

      所以我们只需要线段树维护区间乘积,以及每个质数出没出现过。

      一开始打算用bitset,但是发现 (300) 以内质数只有 (62) 个,不多不少,可以直接 ull存。大概 ll也就够了。

      注意区间乘积,乘标记在区间上算贡献要以幂的形式算上去,而不是像求区间和那样直接乘。一开始没注意到,死活过不去。还有如果是用 ull压位的,注意算集合的时候 1 << i要写成1ull << i

    #define lc o << 1
    #define rc o << 1 | 1
    typedef std::pair<ull, int> pli;
    
    const int N = 4e5 + 7;
    const int M = 300 + 7;
    const int P = 1e9 + 7;
    
    int n, m, x, y, z, a[N];
    char opt[15];
    
    int prt, p[M], np[M], inv[N], id[N];
    inline void Make_Prime(int n) {
    	np[0] = np[1] = inv[1] = 1; 
    	for (int i = 2; i <= n; ++i) {
    		inv[i] = (ll)(P - P / i) * inv[P % i] % P;
    		if (!np[i]) p[++prt] = i, id[i] = prt;
    		for (int j = 1; j <= prt && i * p[j] <= n; ++j){
    			np[i * p[j]] = j;
    			if (i % p[j] == 0) break;
    		}
    	}
    }
    
    inline pli operator + (const pli &a, const pli &b) {return pli(a.fi | b.fi, (ll)a.se * b.se % P);}
    inline int fpow(int x, int y) {
    	int ans = 1;
    	for (; y; y >>= 1, x= (ll)x * x % P) if(y & 1) ans = (ll)ans * x % P;
    	return ans;
    }
    
    struct Node {
    	ull val, add;
    	int mul, tag;
    } t[N << 2];
    inline void Build(int o, int L, int R) {
    	t[o].tag = 1;
    	if (L == R) {
    		int x = a[L]; t[o].mul = a[L];
    		while (x > 1 && np[x]) t[o].val |= 1ull << (np[x] - 1), x /= p[np[x]];
    		if (x > 1) t[o].val |= 1ull << (id[x] - 1); return;
    	}
    	int M = (L + R) >> 1;
    	Build(lc, L, M); Build(rc, M + 1, R);
    	t[o].val = t[lc].val | t[rc].val; t[o].mul = (ll)t[lc].mul * t[rc].mul % P;
    }
    inline void Mul(int o, int L, int R, int l, int r, int x, ull y) {
    	if (l <= L && R <= r) {
    		t[o].tag = (ll)t[o].tag * x % P;
    		t[o].mul = (ll)t[o].mul * fpow(x, R - L + 1) % P;
    		t[o].add |= y; t[o].val |= t[o].add; return;
    	}
    	int M = (L + R) >> 1;
    	if (l <= M) Mul(lc, L, M, l, r, x, y);
    	if (r > M) Mul(rc, M + 1, R, l, r, x, y);
    	t[o].val = t[lc].val | t[rc].val | t[o].add;
    	t[o].mul = (ll)t[lc].mul * t[rc].mul % P *fpow(t[o].tag, R - L + 1) % P;
    }
    inline pli Get(int o, int L, int R, int l, int r, pli add = pli(0, 1)) {
    	if (l <= L && R <= r) return pli(t[o].val, t[o].mul) + pli(add.fi, fpow(add.se, R - L + 1));
    	int M = (L + R) >> 1; pli hkk = add + pli(t[o].add, t[o].tag);
    	if (r <= M) return Get(lc, L, M, l, r, hkk);
    	if (l > M) return Get(rc, M + 1, R, l, r, hkk);
    	return Get(lc, L, M, l, r, hkk) + Get(rc, M + 1, R, l, r, hkk);
    }
    
    inline int GetAns(pli x) {
    	int ans = x.se; ull S = x.fi;
    	for (int i = 1; i <= prt; ++i)
    		if((S >> (i - 1)) & 1) ans = (ll)ans * inv[p[i]] % P * (p[i] - 1) % P;
    	return ans;
    }
    
    int main() {
    	#ifdef hzhkk
    	freopen("hkk.in", "r", stdin);
    	#endif
    	read(n), read(m); Make_Prime(300);
    	for (int i = 1; i <= n; ++i) read(a[i]);
    	Build(1, 1, n);
    	for (int i = 1; i <= m; ++i) {
    		scanf("%s", opt); read(x), read(y);
    		if (*opt == 'M') {
    			read(z); ull hkk = 0; int r = z;
    			while (r > 1 && np[r]) hkk |= 1ull << (np[r] - 1), r /= p[np[r]];
    			if (r > 1) hkk |= 1ull << (id[r] - 1);
    			Mul(1, 1, n, x, y, z, hkk);
    		}
    		else printf("%d
    ", GetAns(Get(1, 1, n, x, y)));
    	}
    }
    
  • 相关阅读:
    【Azure 应用服务】由 Azure Functions runtime is unreachable 的错误消息推导出 ASYNC(异步)和 SYNC(同步)混用而引起ThreadPool耗尽问题
    【Azure API 管理】是否可以将Swagger 的API定义导入导Azure API Management中
    【Azure 应用服务】Azure Function 不能被触发
    【Azure 环境】Azure Key Vault (密钥保管库)中所保管的Keys, Secrets,Certificates是否可以实现数据粒度的权限控制呢?
    【Azure 事件中心】为应用程序网关(Application Gateway with WAF) 配置诊断日志,发送到事件中心
    【Azure 事件中心】azure-spring-cloud-stream-binder-eventhubs客户端组件问题, 实践消息非顺序可达
    【Azure API 管理】Azure API Management通过请求中的Path来限定其被访问的频率(如1秒一次)
    【Azure 环境】前端Web通过Azure AD获取Token时发生跨域问题(CORS Error)
    【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
    【Azure 应用服务】App Service中抓取 Web Job 的 DUMP 办法
  • 原文地址:https://www.cnblogs.com/hankeke/p/CF1114.html
Copyright © 2011-2022 走看看