2017 四川省赛 6/12

emmmm四川省赛的题这么难的嘛。。。。
也不算难,就是做的很憋屈。。。。

A

坑人系列x注意数据范围

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>

using namespace std;

using ll = long long;

void OUT(__int128 x) {
    static int f[200];
    int p = 0;
    if (x == 0)
        puts("0");
    else {
        while (x) {
            f[p] = x % 10;
            x /= 10;
            ++p;
        }
        for (int i = p - 1; i >= 0; --i)
            putchar('0' + f[i]);
        putchar('\n');
    }
}

inline int sgn(long long a) {
	if (a >= 0)
		return 1;
	else
		return -1;
}

inline __int128 Abs(ll x) {
	if (x >= 0)
		return x;
	else {
		__int128 t = x;
		t = -t;
		return t;
	}
}

int main() {
	long long a, b;
	while (scanf("%lld%lld", &a, &b) != EOF) {
		if (sgn(a) * sgn(b) >= 0)
            OUT(Abs(a) / Abs(b));
		else {
            __int128 t1 = Abs(a), t2 = Abs(b);
            putchar('-');
			OUT(((t1 + t2 - 1) / t2));
		}
	}
}

B

C

D

E

显然这个转移的图构成DAG,然后你就支配树一下,在支配树上DP算贡献即可。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <vector>

using namespace std;

int const N = 5005;
int const LOGN = 15;

int fa[N][LOGN];
int pre[N];
int f1[N], f2[N];
vector<int> G[N];
int a[N];
int f[N];
int dep[N];
int n;

int get_lca(int x, int y) {
	if (dep[x] < dep[y])
		swap(x, y);
	for (int i = LOGN - 1; i >= 0; --i) 
		if (dep[fa[x][i]] >= dep[y]) 
			x = fa[x][i];
	if (x == y)
		return x;
	for (int i = LOGN - 1; i >= 0; --i)
		if (fa[x][i] != fa[y][i])
			x = fa[x][i], y = fa[y][i];
	return fa[x][0];
}

void mark(int x, int v) {
	int root = x;
	while (x != n + 1) {
		f1[x] ^= v * v;
		if (x != root)
			f2[x] ^= (v - 1) * (v - 1);
		x = pre[x];
	}
}

int main() {
	ios::sync_with_stdio(0);
	while (cin >> n) {
		memset(fa[n + 1], 0, sizeof(fa[n + 1]));
		memset(f1, 0, sizeof(f1));
		memset(f2, 0, sizeof(f2));
		pre[n + 1] = 0;
		dep[n + 1] = 1;
		int ans = 0;
		for (int i = 1; i <= n; ++i) {
			G[i].clear();
			cin >> a[i];
			f[i] = 1;
			for (int j = 1; j < i; ++j)
				if (a[j] < a[i])
					f[i] = max(f[i], f[j] + 1);
			for (int j = 1; j < i; ++j)
				if (a[j] < a[i] && f[j] == f[i] - 1) 
					G[i].push_back(j);
			if (G[i].size() == 0u)
				G[i].push_back(n + 1);
			int lca = -1;
			for (auto c : G[i]) {
				if (lca == -1)
					lca = c;
				else
					lca = get_lca(c, lca);
			}
			pre[i] = lca;
			dep[i] = dep[pre[i]] + 1;
			mark(i, f[i]);
			fa[i][0] = lca;
			for (int j = 1; j < LOGN; ++j)
				fa[i][j] = fa[fa[i][j - 1]][j - 1];
			ans ^= f[i] * f[i];
		}
		for (int i = 1; i <= n; ++i) 
			cout << (ans ^ f1[i] ^ f2[i]) << ' ';
		cout << '\n';
	}
}

F

这我真不知道应该怎么做,想了想二次曲面还没有旋转的,貌似往8个无穷的方向趋近一下就行的亚子。。。然后再判断一下原点附近就行。

#include <iostream>
#include <cstdio>

using namespace std;

using ll = long long;
using i128 = __int128;

ll const INF = 1e10;

i128 sqr(i128 x) {
	return x * x;
}

bool chk(ll x0, ll y0, ll a, ll b, ll c) {
	return a * sqr(x0) + i128(b) * x0 * y0 + c * sqr(y0) >= 0;
}

int main() {
	int a, b, c;
	while (scanf("%d%d%d", &a, &b, &c) != EOF) {
		bool ans = 1;
		for (int i = -1000; i <= 1000; ++i) {
			int C = a * i * i;
			int B = b * i;
			int A = c;
			if (4 * A * C - B * B < 0) {
				ans = 0;
				break;
			}
		}
		for (int i = -1; i <= 1; ++i)
			for (int j = -1; j <= 1; ++j)
				ans &= chk(i * INF, j * INF, a, b, c);
		if (ans)
			puts("Yes");
		else
			puts("No");
	}
}

G

来自新队友的一发提交。

#include <bits/stdc++.h>
using namespace std;
const int K=2017;
int a,b,c,d;
long long A,B,ans;
long long work(int L,int R)
{
    int first=0;
    for (int i=L;i<=R;i++)
        if (!(i%K))
        {
            first=i;
            break;
        }
    return first?(R-first)/K+1:0;
}
int main()
{
    while (scanf("%d%d%d%d",&a,&b,&c,&d)>0)
    {
        A=work(a,b);
        B=work(c,d);
        ans=A*(d-c+1)+(b-a+1-A)*B;
        printf("%lld\n",ans);
    }
    return 0;
}

H

I

J

K

bitset压位加速一下就可以了的亚子

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <bitset>

using namespace std;

using ll = long long;

int const MOD = 2017;

ll KSM(ll a, ll k) {
	ll ret = 1;
	for (; k; k >>= 1, a = a * a % MOD)
		if (k & 1)
			ret = ret * a % MOD;
	return ret;
}

int dfn[2017];

void Yroot() {
	int x = 5, t = 1;
	for (int i = 1; i < 2017; ++i) {
		dfn[x] = t;
		x = x * 5 % 2017;
		++t;
	}
}

int main() {
	Yroot();
	int n, m;
	while (scanf("%d%d", &n, &m) != EOF) {
		auto f = bitset<2017>();
		for (int o = 1; o <= n; ++o) {
			int x;
			scanf("%d", &x);
			x = dfn[x];
			f ^= ((f << x) | (f >> (n - x)));
			f[x] = f[x] ^ 1;
		}
		cout << f[dfn[m]] << '\n';
	}
}	

L

显然你就枚举一下,就化为3维了,然后复用一下就行。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>

using namespace std;

using ll = long long;

int const MOD = 1e9 + 7;

ll KSM(ll a, ll k) {
	ll ret = 1;
	for (; k; k >>= 1, a = a * a % MOD)
		if (k & 1)
			ret = ret * a % MOD;
	return ret;
}

int const N = 100005;

int a[N];
int n;

ll calc(ll s1, ll s2, ll s3) {
	static ll inv6 = KSM(6, MOD - 2);
	ll fz = KSM(s1, 3) - 3ll * (s2 * s1 % MOD) + 2ll * s3;
	fz %= MOD;
	if (fz < 0)
		fz += MOD;
	return fz * inv6 % MOD;
}

int main() {
	while (scanf("%d", &n) != EOF) {
		for (int i = 1; i <= n; ++i) 
			scanf("%d", &a[i]);
		ll sum1 = 0, sum2 = 0, sum3 = 0, ans = 0;
		for (int i = 1; i <= n; ++i) {
			if (i >= 4) 
				ans = (ans + a[i] * calc(sum1, sum2, sum3) % MOD) % MOD;
			sum1 = (sum1 + a[i]) % MOD;
			sum2 = (sum2 + KSM(a[i], 2)) % MOD;
			sum3 = (sum3 + KSM(a[i], 3)) % MOD;
		}
		cout << ans << '\n';
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值