ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879

A

签到,dfs 或者 floyd 都行。

#include<bits/stdc++.h>
using namespace std; typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e5 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8; LL read() {
LL n = 0;
char a = getchar();
bool flag = 0;
while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
if(flag) n = -n;
return n;
} string S1[22],S2[22];
int n;
int f[111][111]; void work() {
map<string,int> mp;
int tot = 0;
for(int i = 1;i <= n;i ++) {
string s1 = S1[i],s2 = S2[i];
if(!mp[s1]) mp[s1] = ++ tot;
if(!mp[s2]) mp[s2] = ++ tot;
} for(int i = 1;i <= tot;i ++) {
for(int j = 1; j <= tot;j ++) {
f[i][j] = 0;
}
} for(int i = 1;i <= n;i ++) {
string s1 = S1[i],s2 = S2[i];
int x = mp[s1],y = mp[s2];
if(f[y][x]) {
cout << s1 << " " << s2 << endl;
return ;
}
f[x][y] = 1;
for(int k = 1;k <= tot;k ++) {
for(int u = 1;u <= tot;u ++) {
for(int v = 1;v <= tot;v ++) {
if(f[u][k] && f[k][v]) {
f[u][v] = 1;
}
}
}
}
for(int u = 1;u <= tot;u ++) {
for(int v = 1;v <= tot;v ++) {
if(f[u][v]) {
if(u == v || f[v][u]) {
cout << s1 << " " << s2 << endl;
return ;
}
}
}
}
/* for(int u = 1;u <= tot;u ++,puts(""))
for(int v = 1;v <= tot;v ++)
printf("%d ",f[u][v]);
puts("");*/
}
puts("0");
return ;
} int main() {
while(~scanf("%d",&n)) {
for(int i = 1;i <= n;i ++) {
string s1,s2;
cin >> s1 >> s2;
S1[i] = s1;
S2[i] = s2;
}
work();
}
}

B

阅读题,模拟,坑点多,WA了好多发,换了个写法就过了,不知道为什么

C

题意:定义 (a,b,c) 为一组勾股数,c 是斜边长度,且 (a,b,c) 与 (b,a,c) 看做一组。问 c<=n 的三元组有多少对。 \(n \le 10^9\)

key:推公式

我真的是惊了,为什么要出这种带了板子就会的题。

首先你要知道勾股数的构造才能做这个题,即 \(a=m^2-n^2,b=2mn,c=m^2+n^2\) 。所有勾股数不好算,所以我们对本原勾股数计数,乘上个倍数即可。在上式中, \((a,b,c)\) 为一组本原勾股数当且仅当 $\gcd(m,n)=1 \text{且 \(m,n\)为一奇一偶}$ 。

设 \(f(n)\) 为以 n 为斜边的三元组对数, \(g(n)\) 为以 n 为斜边的本原勾股数个数,\(F,G\) 为对应的前缀和,那么有:

\[f = g \times 1 \to F=\sum_{1 \le i\le n}G(n/i) \\
G(n) = \sum_{1\le x\le N} \sum_{1 \le y \le N} [x^2+y^2 \le N][\gcd(x,y)=1][\text{x is odd, y is even}]
\]

然后就对 G 随便推一波就行了。形式是一个调和级数。

不预处理的话复杂度是 \(O(Tn^{3/4}\ln n)\),预处理前根号下三分之二次方的复杂度就变成 \(O(Tn^{2/3}\ln n)\) 。预处理就直接用上面给出的这个 G ,随便积分一下算出来预处理前 B 项的复杂度是 \(O(B \ln B)\) 。实测了一下大概取 \(10^7\) 比较优,十组 \(10^9\) 只跑 0.6s 左右。

#include<bits/stdc++.h>
using namespace std; typedef unsigned long long ULL;
typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e7 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8; LL read() {
LL n = 0;
char a = getchar();
bool flag = 0;
while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
if(flag) n = -n;
return n;
} int preG[SZ];
const int MAXN = 1e7;
int mu[100100];
bool vis[100100];
int pri[100100]; void preWork(int n) {
for(int x = 1;x * x <= n;x += 2) {
for(int y = 2;x * x + y * y <= n;y += 2) {
if(__gcd(x,y) == 1)
preG[x*x+y*y] ++;
}
}
for(int i = 1;i <= n;i ++) preG[i] += preG[i-1]; n = 100000;
mu[1] = 1;
for(int i = 2;i <= n;i ++) {
if(!vis[i]) pri[++ pri[0]] = i,mu[i] = -1;
for(int j = 1,m;j <= pri[0] && (m=i*pri[j]) <= n;j ++) {
vis[m] = 1;
if(i%pri[j] == 0) {
mu[m] = 0;
}
else {
mu[m] = -mu[i];
}
}
}
} LL G(int n) {
if(n <= MAXN) return preG[n];
LL ans = 0;
for(int d = 1;d * d * 2 <= n;d ++) {
int tmp = 0;
int d2 = d*d,m = n/d2;
for(int x = 1,lim = sqrt(n-d*d)/d;x*x <= m;x ++) {
while(lim*lim+x*x > m) lim --;
if((d*x)&1) tmp += lim / 2;
else tmp += lim;
}
ans += mu[d] * tmp;
}
return ans / 2;
} int main() {
// freopen("C.in","r",stdin);
preWork(MAXN);
int T = read();
while(T --) {
int n = read();
LL ans = 0;
for(int i = 1,r;i <= n;i = r + 1) {
r = n / (n / i);
ans += G(n / i) * (r-i+1);
}
printf("%lld\n",ans);
}
}
/**
3080075432
*/

D

题意:你要从 0 跳到 200,第 i 个位置能跳到第 i+1 和 i+2 上。你可以设置若干个传送门,一个位置只有一个入口,出口任意。跳到入口处就立马被传送到出口,如果构成环则永远出不去。求使得走到 200 的方案数恰好为 M 的一组传送门设置方案。 \(M < 2^{32}\)

key:构造

如果你想 ban 掉一个位置,那么一定是原地传送最优。考虑 ban 掉第 i 个位置,那么设第 i-1 个位置的方案数是 x,那么从第 i-1 开始的方案数是 \(x,0,x,x,2x\) 。这样就容易想到二进制。

如果想凑出 \(2^i\) ,那么应该设置为 \(2^i,X,2^i,2^i,2^{i+1},Y\) 。如果不想,那么应该是 \(2^i,2^i,2^{i+1},Y\) 。其中 X 是传到终点,Y 是原地传送。

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
ll m;
ll f[304];
vector<pa>ans;
int w33ha(){
ans.clear();
memset(f,0,sizeof(f));
f[0]=1;
f[1]=1;
//int a=0;
int B = 0;
for(ll i=0;i<=32;i++){
if((m&(1LL<<i))){
ans.push_back({B+1,199});
ans.push_back({B+5,B+5});
B += 6;
}
else{
ans.push_back({B+3,B+3});
B += 4;
}
}
ans.push_back({197,197});
ans.push_back({198,198});
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++){
printf("%d %d\n",ans[i].first,ans[i].second);
}
return 0;
} int main(){
while(scanf("%lld",&m)!=EOF)w33ha();
return 0;
}

E

F

题意:给一个有向图,定义 (u,v) 合法当且仅当 u 能走到 v,权值为 u^v。Q 次询问每次问第 k 大的权值。 \(n \le 5*10^4,m \le 2*10^5 , Q \le 10,T \le 3, k \le 10^9\)

key:bitset

容易想到二分答案,问题在于 check 。如果我们处理出来点 x 能走到哪些点,设这个集合是 S,那么就要找有多少个 \(y \in S\) ,使得 x^y>mid。这个是在 trie 上做的。所以就不用二分答案了,直接在 trie 上贪心。

考虑从 trie 上走的过程:贪心选 0,如果不行,那么走 1。判断是否不行是用子树和,这就是值域上的区间和,所以现在问题变成查询标号小于等于一个数的个数。

所以有一个 bitset 的做法。用 tarjan+拓扑排序 预处理 bitset 的复杂度是 \(O((n+m)n/W)\),模拟 trie 上的复杂度是 \(O(n^2/W\log n)\) ,后者应该是不行的。

所以手写 bitset ,对 n/W 位建一个前缀和。后者的复杂度为 \(O(n \log n)\) ,需要用到 __builtin_popcountll 。

所以这个题的总复杂度为 \(O(T((n+m)n/W+Qn\log n))\) ,空间复杂度为 \(O(n^2/W)\)

(这里手写了 bitset ,由于差分的性质所以改成前缀和,由于 __builtin_popcountll 而优化了查询的复杂度。如果不是二进制 1 的个数那么查询的复杂度要再乘一个 W,如果不满足差分性质可以在 bitset 上分块)

#include<bits/stdc++.h>
using namespace std; typedef unsigned long long ULL;
typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 5e4 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8; LL read() {
LL n = 0;
char a = getchar();
bool flag = 0;
while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
if(flag) n = -n;
return n;
} struct Bitset {
#define W (64) int n;
ULL bits[SZ / W + 10];
int num[SZ / W + 10]; void preWork() {
for(int i = 0;i <= n/W;i ++) num[i] = __builtin_popcountll(bits[i]);
for(int i = n/W-1;i >= 0;i --) num[i] += num[i+1];
// for(int i = 0;i < m;i ++) printf("%d ",sum[i]); puts("");
// for(int i = 0;i <= n/W;i ++) printf("%llu ",bits[i]); puts("");
} int ask(int x) {
if(x > n) return 0;
int blockid = x / W;
int ans = __builtin_popcountll(bits[blockid]>>(x%W));
blockid ++;
if(blockid <= n/W) ans += num[blockid];
return ans;
} int ask(int l,int r) {
return ask(l) - ask(r+1);
} void Or(const Bitset &t) {
for(int i = 0;i <= n / W;i ++) bits[i] |= t.bits[i];
} void Copy(const Bitset &t) {
n = t.n;
for(int i = 0;i <= n / W;i ++) bits[i] = t.bits[i];
} void Set(int x) {
bits[x/W] |= 1llu << (x%W);
} void init(int nn) {
n = nn; //n ++;
for(int i = 0;i <= n / W;i ++) bits[i] = 0;
} void print() {
for(int i = 0;i < n;i ++) {
if(bits[i/W] >> (i%W) & 1)
printf("%d ",i);
}
puts("");
} #undef W
}bs[SZ]; struct Tarjan { int n;
int dfn[SZ],low[SZ],dfs_clock,scccnt,sccnum[SZ];
vector<int> g[SZ],sccnodes[SZ];
stack<int> S; void dfs(int u) {
dfn[u] = low[u]= ++ dfs_clock;
S.push(u);
for(int v : g[u]) {
if(!dfn[v]) {
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(!sccnum[v])
low[u] = min(low[u],dfn[v]);
}
if(low[u] == dfn[u]) {
scccnt ++;
while(1) {
int x = S.top(); S.pop();
sccnum[x] = scccnt;
sccnodes[scccnt].push_back(x);
if(x == u) break;
}
}
} vector<int> g2[SZ];
int cd[SZ]; void work(Bitset bs[]) {
for(int i = 1;i <= n;i ++)
if(!dfn[i])
dfs(i);
// for(int u = 1;u <= n;u ++) printf("%d ",sccnum[u]); puts("");
for(int u = 1;u <= n;u ++)
for(int v : g[u])
if(sccnum[u] != sccnum[v]) {
g2[sccnum[v]].push_back(sccnum[u]);
cd[sccnum[u]] ++;
}
static Bitset tmp[SZ];
for(int i = 1;i <= scccnt;i ++) {
tmp[i].init(n); //tmp[i].print();
for(int x : sccnodes[i])
tmp[i].Set(x);
}
queue<int> q;
for(int i = 1;i <= scccnt;i ++)
if(cd[i] == 0) {
q.push(i);
}
while(q.size()) {
int v = q.front(); q.pop();
// printf("%d: ",v); tmp[v].print();
for(int x : sccnodes[v]) bs[x].Copy(tmp[v]);
for(int u : g2[v]) {
tmp[u].Or(tmp[v]);
cd[u] --;
if(cd[u] == 0) {
q.push(u);
}
}
}
} void addEdge(int x,int y) {
g[x].push_back(y);
} void init(int nn) {
n = nn;
for(int i = 1;i <= scccnt;i ++) {
g2[i].clear();
sccnodes[i].clear();
cd[i] = 0;
}
for(int i = 1;i <= n;i ++) {
g[i].clear();
dfn[i] = low[i] = sccnum[i] = 0;
}
scccnt = 0;
dfs_clock = 0;
} }tarjan; int now[SZ]; void work(int n,int &mid,int id,int &k) {
LL ans = 0;
for(int i = 1;i <= n;i ++) {
int t,l,r;
if(i>>id&1)
t = bs[i].ask(l=now[i],r=now[i]+(1<<id)-1);
else
t = bs[i].ask(l=now[i]+(1<<id),r=now[i]+(2<<id)-1);
ans += t;
// printf("%d: [%d,%d] %d\n",i,l,r,t);
}
//cout << id << " " << ans << " " << k << endl;
if(k <= ans) {
for(int i = 1;i <= n;i ++) {
if((i>>id&1) == 0) {
now[i] |= 1 << id;
}
}
mid |= 1 << id;
}
else {
k -= ans;
for(int i = 1;i <= n;i ++) {
if(i>>id&1) {
now[i] |= 1 << id;
}
}
}
//cout << k << endl;
// for(int i = 1;i <= n;i ++) printf("%d ",now[i]); puts("");
} int main() {
// freopen("F.in","r",stdin); freopen("my.out","w",stdout);
int T = read();
while(T --) {
int n = read(),m = read(),Q = read();
tarjan.init(n);
for(int i = 1;i <= m;i ++) {
int x = read(),y = read();
tarjan.addEdge(x,y);
}
tarjan.work(bs);
// for(int i = 1;i <= n;i ++) bs[i].print();
for(int i = 1;i <= n;i ++){
bs[i].preWork();
}
while(Q --) {
int k = read();
int ans = 0;
for(int i = 1;i <= n;i ++) now[i] = 0;
for(int i = 16;i >= 0;i --) {
work(n,ans,i,k);
}
printf("%d\n",ans);
}
}
}

G

题意:给一个 n 次多项式 F,求一个 n 阶多项式 G,使得 G 的每一个根(不一定实根)为 F 的对应根的 m 次幂。 \(n+m \le 10,|a_i| \le 120\),保证 G 的系数 \(< 10^{12}\)

key:牛顿恒等式

设多项式 \(F(x)=\sum_{0\le i \le n} a_ix^i\) ,设其所有根为 \(x_1,x_2...x_n\) (包括复根) ,设 \(S_k=\sum_{i=1}^nx_i^k\) ,\(b_i=a_{n-i}\) 。则对于任意的正整数 k ,有

\[\sum_{i=1}^kS_ib_{k-i}+k\times b_k=0
\]

所以只要用系数递推出 n*m 个 S,然后反推出答案即可。因为 \(SG_i=SF_{i \cdot m}\) 。

#include<bits/stdc++.h>
using namespace std; typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e5 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8; LL read() {
LL n = 0;
char a = getchar();
bool flag = 0;
while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
if(flag) n = -n;
return n;
} LL a[111],b[111],s[111]; int main() {
int n,m;
while(~scanf("%d%d",&n,&m) && n && m) {
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(s,0,sizeof s);
for(int i = 0;i < n;i ++) a[i] = read(); a[n] = 1;
reverse(a,a+n+1);
for(int k = 1;k <= n*m;k ++) {
s[k] = -k*a[k];
for(int i = 1;i < k;i ++) s[k] -= s[i] * a[k-i];
}
b[0] = 1;
for(int k = 1;k <= n;k ++) {
b[k] = 0;
for(int i = 1;i <= k;i ++) b[k] -= s[i*m] * b[k-i];
b[k] /= k;
}
for(int i = n;i >= 1;i --) {
printf("%lld%c",b[i],i==1?'\n':' ');
}
}
}

H

题意:定义字符串 A 几乎匹配 B 当且仅当 B 存在一个子串,与 A 长度相同且至多一个字符不同。给出 A,求有多少个长度为 m 的 B。字符集是 {0,1}。 \(|A|,m\le 40\)

key:dp

主要怕算重,这个只需要找到第一次匹配的位置即可。\(f_{i,j}\) 表示 A 第一次出现位置在 \([i-|A|+1,i]\) 且第 j 位不同的方案数,有:

\[f_{i,j} = 2^{i-|A|}-\sum_{k\le i-|A|,l}f_{k,l}\times 2^{i-|A|-k}-\sum_{i-|A|< k< i}f_{k,l}\times w(i,j,k,l)
\]

即前面随便填的,减去出现过的。第一项是出现位置与当前串不相交的个数,第二项是相交的个数。注意这里相交可能不合法,所以需要一个 \(w(i,j,k,l)\) 来 check,合法时返回 1,否则返回 0。这个可以预处理一下。总复杂度是 \(O(m^2|A|^2)\)

#include<bits/stdc++.h>
using namespace std; typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e5 + 10;
const int INF = 1e9 + 10;
const int mod = 1e9 + 7;
const LD eps = 1e-8; LL read() {
LL n = 0;
char a = getchar();
bool flag = 0;
while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
if(flag) n = -n;
return n;
} char s[55];
int n,m;
LL f[55][55];
LL g[55][55][55]; bool isequ(int len,int p1,int p2) {
string s1,s2;
for(int i = 1;i <= len;i ++) {
if(i==p1) {
if(s[i] == '0') s1 += '1';
else s1 += '0';
}
else s1 += s[i];
}
for(int i = n-len+1;i <= n;i ++) {
if(i==p2) {
if(s[i] == '0') s2 += '1';
else s2 += '0';
}
else s2 += s[i];
}
return s1 == s2;
} int main() {
int T = read();
while(T --) {
n = read(),m = read();
scanf("%s",s+1);
for(int j = 0;j <= n;j ++) {
for(int k = 1;k < n;k ++) {
for(int l = 0;l <= n;l ++) {
if(isequ(k,j,l)) {
g[j][k][l] = 1;
}
else {
g[j][k][l] = 0;
}
}
}
}
for(int i = 1;i <= m;i ++) {
for(int j = 0;j <= n;j ++) {
if(i-n < 0) {
f[i][j] = 0;
continue;
}
LL ans = 1ll<<(i-n);
for(int k = 1;k < i;k ++) {
for(int l = 0;l <= n;l ++) {
if(k <= i-n) {
ans -= f[k][l] * (1ll<<(i-n-k));
}
else {
ans -= f[k][l] * g[j][k-i+n][l];
}
}
}
f[i][j] = ans;
}
}
LL ans = 0;
for(int i = 1;i <= m;i ++) {
for(int j = 0;j <= n;j ++) {
ans += f[i][j] * (1ll<<(m-i));
}
}
printf("%lld\n",ans);
}
}

I

打表找规律

J

题意:二维平面上给出 n 个点,求所有锐角三角形面积之和。 \(n \le 2000\)

key:扫描线

总面积减去直角三角形面积减去钝角三角形面积。这三个都能在极角排序的序列上用双指针定位。算面积用前缀和就行。

#include<bits/stdc++.h>
using namespace std; typedef __int128 int128;
typedef long long LL;
typedef long double LD;
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
const int SZ = 1e6 + 10;
const int INF = 1e9 + 10;
const int mod = 998244353;
const LD eps = 1e-14;
const LD PI = acos(-1); LL read() {
LL n = 0;
char a = getchar();
bool flag = 0;
while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
while(a <= '9' && a >= '0') { n = n * 10 + a - '0',a = getchar(); }
if(flag) n = -n;
return n;
} LL ksm(LL a,LL b) {
LL ans = 1;
while(b) {
if(b&1) ans = a * ans % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
} struct Point {
LL x,y;
LL vx,vy;
Point(LL _x=0,LL _y=0,LL _vx=0,LL _vy=0):x(_x),y(_y),vx(_vx),vy(_vy) { }
Point operator -(Point &o) { return Point(x-o.x,y-o.y); }
Point operator +(Point &o) { return Point(x+o.x,y+o.y); }
Point getV() { return Point(vx,vy); }
}a[SZ],b[SZ],sb[SZ]; int128 operator ^(Point &a,Point &o) { return (int128)a.x*o.y-(int128)a.y*o.x; }
int128 operator *(Point &a,Point &o) { return (int128)a.x*o.x+(int128)a.y*o.y; } int getxx(Point a) {
if(a.x>0 && a.y>=0) return 1;
if(a.x<=0 && a.y>0) return 2;
if(a.x<0 && a.y<=0) return 3;
if(a.x>=0 && a.y<0) return 4;
} bool operator <(Point &a,Point &b) {
if(getxx(a)!=getxx(b)) return getxx(a) < getxx(b);
return (int128)a.x*b.y>(int128)a.y*b.x;
} bool isSameAlpha(Point &a,Point &b) {
if(getxx(a) != getxx(b)) return false;
return (a^b) == 0;
} int main() {
// freopen("J.in","r",stdin); freopen("2.out","w",stdout);
int T = read();
while(T --) {
int n = read();
for(int i = 1;i <= n;i ++) {
a[i].x = read();
a[i].y = read();
} LL ans = 0;
LL sjx = 0,zjsjx = 0,djsjx = 0;
for(int o = 1;o <= n;o ++) {
int len = 0;
for(int i = 1;i <= n;i ++) {
if(i == o) continue;
b[++ len] = a[i] - a[o];
b[len].vx = b[len].x % mod;
b[len].vy = b[len].y % mod;
b[++ len] = a[o] - a[i];
}
sort(b+1,b+1+len); int tot = 0;
for(int i = 1,j = 1;i <= len;i ++) {
if(i == len || !isSameAlpha(b[i],b[i+1])) {
Point ans = b[j]; j++;
while(j<=i) {
ans.vx = (ans.vx + b[j].vx) % mod;
ans.vy = (ans.vy + b[j].vy) % mod;
j ++;
}
b[++ tot] = ans;
}
}
len = tot;
for(int i = 1;i <= len;i ++) {
b[i+len].x = b[i].x;
b[i+len].y = b[i].y;
b[i+len].vx = b[i].vx;
b[i+len].vy = b[i].vy;
}
len*=2;
sb[1] = Point(b[1].vx,b[1].vy);
for(int i = 2;i <= len;i ++) {
sb[i].x = (sb[i-1].x + b[i].vx) % mod;
sb[i].y = (sb[i-1].y + b[i].vy) % mod;
} /* printf("%d\n",o);
for(int i = 1;i <= len;i ++) {
printf("(%3lld,%3lld) (%3lld,%3lld)\n",b[i].x,b[i].y,b[i].vx,b[i].vy);
//printf("(%lld,%lld)\n",b[i].vx,b[i].vy);
}*/
// for(int i = 1;i <= len;i ++) printf("(%lld,%lld)\n",sb[i].x,sb[i].y); int r3 = 1,r2 = 1;
LL t1 = 0,t2 = 0,t3 = 0;
for(int i = 1;i <= len/2;i ++) {
Point now = b[i].getV();
// if(now.x == 0 && now.y == 0) continue;
while(r2<=len&&b[i]*b[r2]>0) r2++;
while(r3+1<=len&&(b[i]^b[r3+1])>0) r3++;
Point b1 = (sb[r3] - sb[i]);
Point b2 = (sb[r3] - sb[r2 - 1]);
(t1 += (now ^ b1) % mod) %= mod;
(t3 += (now ^ b2) % mod) %= mod;
// printf("%d %d %d %d %lld\n",i,r1,r2,r3);
}
// printf("-%d %lld %lld %lld\n",o,t1,t2,t3);
(sjx += t1) %= mod;
(zjsjx += t2) %= mod;
(djsjx += t3) %= mod;
}
//printf("%lld %lld %lld\n",sjx,zjsjx,djsjx);
(ans += sjx * ksm(3,mod-2) % mod - zjsjx - djsjx) %= mod;
ans += mod; ans %= mod; printf("%lld\n",ans);
}
} /**
5
5 4
2 4
3 5
3 1 7
0 0
0 1
0 -1
1 0
2 0
-1 0
-2 0 */

ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879的更多相关文章

  1. hihoCoder #1871 : Heshen's Account Book-字符串暴力模拟 自闭(getline()函数) (ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction B) 2018 ICPC 北京区域赛现场赛B

    P2 : Heshen's Account Book Time Limit:1000ms Case Time Limit:1000ms Memory Limit:512MB Description H ...

  2. hihoCoder #1870 : Jin Yong’s Wukong Ranking List-闭包传递(递归) (ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction A) 2018 ICPC 北京区域赛现场赛A

    P1 : Jin Yong’s Wukong Ranking List Time Limit:1000ms Case Time Limit:1000ms Memory Limit:512MB Desc ...

  3. 2018-2019, ICPC, Asia Yokohama Regional Contest 2018 K

    传送门:https://codeforces.com/gym/102082/attachments 题解: 代码: /** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ...

  4. 2018 ACM-ICPC Asia Beijing Regional Contest (部分题解)

    摘要 本文主要给出了2018 ACM-ICPC Asia Beijing Regional Contest的部分题解,意即熟悉区域赛题型,保持比赛感觉. Jin Yong’s Wukong Ranki ...

  5. ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków

    ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...

  6. 2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)

    2019-2020 ICPC, Asia Jakarta Regional Contest (Online Mirror, ICPC Rules, Teams Preferred) easy: ACE ...

  7. The 2018 ACM-ICPC Asia Beijing Regional Contest

    http://hihocoder.com/problemset/problem/ #1870 : Jin Yong’s Wukong Ranking List 我是每加1个点就dfs判断1次. 正解是 ...

  8. 2018 ICPC Asia Jakarta Regional Contest

    题目传送门 题号 A B C D E F G H I J K L 状态 Ο . . Ο . . Ø Ø Ø Ø . Ο Ο:当场 Ø:已补 .  :  待补 A. Edit Distance Thin ...

  9. Gym - 101981K The 2018 ICPC Asia Nanjing Regional Contest K.Kangaroo Puzzle 暴力或随机

    题面 题意:给你1个20*20的格子图,有的是障碍有的是怪,你可以每次指定上下左右的方向,然后所有怪都会向那个方向走, 如果2个怪撞上了,就融合在一起,让你给不超过5w步,让所有怪都融合 题解:我们可 ...

随机推荐

  1. HDU - 6025 Coprime Sequence(前缀gcd+后缀gcd)

    题意:去除数列中的一个数字,使去除后数列中所有数字的gcd尽可能大. 分析:这个题所谓的Coprime Sequence,就是个例子而已嘛,题目中没有任何语句说明给定的数列所有数字gcd一定为1→_→ ...

  2. HDU 5480:Conturbatio 前缀和

    Conturbatio Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tota ...

  3. JS ~ Promise.reject()

    概述: Promise.reject(reason)方法返回一个带有拒绝原因reason参数的Promise对象. 语法 Promise.reject(reason); reason :  表示Pro ...

  4. cnblogs今天挂了

    刚打算搬进来常驻cnblogs,好死不死,它今天11点40分左右挂了.真是不让人省心: 今天把这后面这几个月的随笔放过来,希望能不会被清掉:

  5. 很多内容是转载或copy各个大佬的

    很多内容是转载或copy各个大佬的

  6. DBUtils模版CRUD

    准备:导包 1.创建c3p0-config.xml配置文件放在src下 <?xml version="1.0" encoding="UTF-8"?> ...

  7. QSignalMapper is deprecated

    今天参考 qt4 的书籍,在 qt5 的平台上面,用了 QSignalMapper,结果收到警告" QSignalMapper is deprecated". 经过一番查找,找到了 ...

  8. java中内存的划分

    java中内存的划分 栈(stack):存放的都是方法中的局部变量.方法的运行一定要在栈当中运行. 局部变量:方法的参数,或者是方法{}内部的变量 作用域:一旦超出作用域,立刻从占内存当中消失. 堆( ...

  9. 阅读笔记--java内存模型原理

    在阅读本篇文章之前,我所理解的和上网了解到的java内存模型原理如下: 不同架构的物理计算机可以有不一样的内存模型,Java 虚拟机也有自己的内存模型.Java 虚拟机规范中试图定义一种 Java 内 ...

  10. Git--记一次丢失本地记录但是代码已提交到gerrit

    参考 https://blog.csdn.net/yucendulang/article/details/76199913 https://stackoverflow.com/questions/28 ...