AtCoder Regular Contest 102

题目链接:https://arc102.contest.atcoder.jp/assignments

C:

大意:给一个n一个k([1,2e5]),三元组a,b,c,a + b, b + c, a + c都是k的倍数,求出这样的三元组的个数

一个小思维题,还是比较好想的,对k分奇偶讨论一下

k为奇数,显然只有三个数都是k的倍数才行

k为偶数,1,三个数都是k的倍数

                2,三个数都是相邻k的倍数的中位数,比如k = 4,n = 11那么选2,6,10也满足条件

开始没开ll,没想到开ll的点在哪

低级错误

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
 
#define int ll
 
int32_t main()
{
	int n, k; cin >> n >> k;
	int t = n / k;
	ll ans = 0;
	if(k & 1){
		ans = t * t * t;
	} 
	else{
		int t2 = t;
		if(n % k >= k / 2) t2++;
		ans = t * t * t + t2 * t2 * t2;
	}
	cout << ans << endl;
	return 0;
}

D:

题目大意:

给一个L,让你构造出一个有向图,满足以下条件。

1.n个点m条边,n<=20, m <= 60,每条边有一个权重([0, 1e6]),可以有平行边

2,边的指向永远是编号小的指向编号大的

3,从节点1到节点n恰好有L条路,并且这L条路的长度正好是[0, L-1]

总感觉这个数据范围在疯狂暗示,不过还是想不到解法。

在网上看了一个:

首先,不妨就令有20个点。

对于i[2, 19],与i+1之间建两条边,权值分别为0,2^(20-i-1),这样我们就能得到所有的位。

描述的不是很清楚。。说说这样构造的目的。比如说给个L正好为2的幂,那么加一条边就能很方便的构造出图了。

那么现在考虑给的数不是2的幂,直接说结论吧,我实在是无法理解这个思路的过程。

从低位到高位考虑:先求出这个1是第几位的(p)。在1, 20 - p两个点之间建一条权值为l ^ lowbit(x)的边。还有就是p=19的时候特判一下。

能想到这个思路的正确性。很巧妙。

Ac Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;

struct node{
	int u, v, w;
	node(int tu, int tv, int tw){
		u = tu, v = tv, w = tw;
	}
};

vector<node> ans;

int32_t main()
{
	int l; scanf("%d", &l);
	for(int i = 2; i <= 19; i++){
		ans.pb(node(i, i + 1, 0));
		ans.pb(node(i, i + 1, (1 << (20 - i - 1))));
	}
	while(l){
		int p = log2(lowbit(l));
		if(p == 19){
			ans.pb(node(1, 2, 0));
			ans.pb(node(1, 2, 1 << 18));
		}
		else ans.pb(node(1, 20 - p, l ^ lowbit(l)));
		l ^= lowbit(l);
	}
	printf("%d %d\n", 20, ans.size());
	for(auto i : ans){
		printf("%d %d %d\n", i.u, i.v, i.w);
	}
	return 0;
}

脑阔疼,学了数位dp一定回来看看这题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值