10.24afternoon清北学堂刷题班


/*
这是什么题...
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm> #define N 100007
#define ll long long using namespace std;
ll n,m,cnt;
ll a[N],b[N]; inline ll read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} inline int cmp(ll x,ll y)
{
return x>y;
} int main()
{
freopen("stone.in","r",stdin);
freopen("stone.out","w",stdout);
int T,res;T=read();
while(T--)
{
ll ans=;
n=read();m=read();
for(int i=;i<=n;i++) a[i]=read();
for(int i=;i<=m;i++) b[i]=read();
sort(a+,a+n+,cmp);
sort(b+,b+m+);
for(int i=;i<=n;i++)
{
if(a[i]<b[i]) break;
if(i>m) break;
ans+=a[i]-b[i];
}
cout<<ans<<endl;
}
fclose(stdin);fclose(stdout);
return ;
}


/*
因为二进制的每一位是互相独立的,只需要算出m*n的矩阵或起来是1的方案数
最后算k次方
容斥原理 总情况2^(n*m)
由于“i-1行j列”和“i行j-1列”的重复计算
使得“i行j列”的情况多减了,需要与上述运算的符号相反
即:i,j组合的符号是根据上面的计算推出来的
res:仅考虑i行j列中没有1的情况总数
C(n,i)*C(m,j)是把行列选出来
Pow(2^(n*m-i*m-j*n+i*j))是说:剩下的格子随意,当前仅考虑选出的i行j列中没有1
*/
#include<bits/stdc++.h> #define N 100005
#define ll long long
#define mod 1000000007 using namespace std;
long long a[]; void pre()
{
a[]=;
for(int i=; i<=; i++) a[i]=a[i-]*i%mod;
} inline void putout(long long x)
{
char c[];
int k=;
if(x<) putchar('-'),x=-x;
do
{
c[++k]=x%+;
x/=;
}
while(x);
while(k) putchar(c[k--]);
} inline long long ksm(long long now,int k)
{
long long mul=now;
long long ret=1LL;
while(k)
{
if(k%)
{
ret=ret*mul%mod;
}
mul=mul*mul%mod;
k>>=;
}
return ret;
} long long C(int n,int m)
{
ll ret=1LL*(a[n]*ksm(a[m],mod-)%mod)*
ksm(a[n-m],mod-)%mod;
return ret;
} int main()
{
freopen("code.in","r",stdin);
freopen("code.out","w",stdout);
int T;
pre();
scanf("%d",&T);
while(T--)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
long long ans=;
for(int i=; i<=n; i++) for(int j=; j<=m; j++)
{
int plus=((i+j)%) ? -:;
long long fast=ksm(,n*m-i*m-j*n+i*j);
long long res=(1LL*C(n,i)*C(m,j)%mod)*fast%mod;
ans=(ans+res*plus)%mod;
}
ans=(ans+mod)%mod; ans=ksm(ans,k);
printf("%I64d\n",ans);
}
return ;
}



/* 环有四种存在情况
1.三条边已知
2.两条边已知
3.一条边已知
4.没有边已知
1.首先考虑三条边已知
对于每个点,记录出度,并把每个点连着的点用vector存储,按照点的编号大小排序
从一个点x出发,沿着一条边走到另一个点y,由此先确定两个点x,y
设置俩指针,同时扫它们连着的点,扫到相同的,ans+1
此过程需要做两个标记,
一个在点上,用于避免2.中点x连出的俩点直接相连的情况
一个在边上,用于计算3.中与一条边的两端点x y都不相连的点的个数
考虑贡献:
如果三边各不相同,ans++;
如果有相同的边,没有贡献。
2.考虑两条边已知
一个点连出的边按照帮(yan)派(se)编号排序
对于每个点x,记录出度(假设为n),则环的数量:C(n,2)-(x连出的俩点之间直接相连)
此处需要一个标记,在1.步骤中找到三元环时需要在起点x标记从x连出的点直接相连的情况
考虑贡献:
排序后的边,会呈几段分布,每段中都是颜色相同的,如果一个点连出的俩边颜色相同,那这仨点围成的环就不会产生贡献,用组合数求出不会贡献的情况个数,就可以计算出能产生贡献的情况数,每个能产生贡献的环的贡献都是(m-2)
3.考虑一条边已知
从一个点x出发,到另一个点y,需要找到这样一个点:既不与x相连,也不与y相连
可以通过在步骤1.中做标记实现
考虑贡献:
每个环的贡献:(m-1)*(m-2)
4.没有边已知
那么环的个数可以根据上面的个数直接算出来
每个环对答案的贡献:m*(m-1)*(m-2) 哦漏了
还需要考虑一种情况,在两条边已知的情况下,如果连出的两条边颜色相同,
并且会有第三边将炼出的两个节点连接,那么我们容斥的时候还会多算他一次,还要再次考虑回去。
方法是在找三元环的时候,假如其中两条边相等,那么将这两条边的公共节点打一次标记。
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
using std::vector;
typedef unsigned int uint;
const int EDGE_SIZE = ;
const int POINT_SIZE = ; struct edge_list
{
int point, color;
uint tri;
edge_list();
edge_list(int, int);
bool operator < (const edge_list & ) const;
};
struct edge_tuple
{
int u, v, color;
void get();
}; int getint();
uint comb_2(int); // equal to C(n, 2)
uint comb_3(int); // equal to C(n, 3)
void add_edge(int, int, int);
void init(int);
bool cmp_color(const edge_list & , const edge_list & ); edge_tuple a[EDGE_SIZE];
vector<edge_list> e[POINT_SIZE];
vector<std::pair<int, int> > common;
int deg[POINT_SIZE];
uint tri[POINT_SIZE];
uint tri0[POINT_SIZE]; int main()
{
freopen("triangle.in", "r", stdin);
freopen("triangle.out", "w", stdout);
uint T, n, m, p;
uint ans;
for (T = getint(); T; T--)
{
n = getint(), m = getint(), p = getint();
uint tmp = m * (m - ) * (m - );
init(n);
for (int i = ; i < p; i++)
{
a[i].get();
deg[a[i].u]++;
deg[a[i].v]++;
}
for (int i = ; i < p; i++)
if (deg[a[i].u] < deg[a[i].v])
add_edge(a[i].u, a[i].v, a[i].color);
else
add_edge(a[i].v, a[i].u, a[i].color);
for (int i = ; i <= n; i++)
std::sort(e[i].begin(), e[i].end());
ans = comb_3(n) * tmp; //type3
for (int u = ; u <= n; u++)
for (int i = ; i < e[u].size(); i++)
{
int v = e[u][i].point;
int j = , k = ;
common.clear();
while (j < e[u].size() && k < e[v].size())
{
for ( ; j < e[u].size() && e[u][j].point < e[v][k].point; j++);
if (j >= e[u].size()) break;
for ( ; k < e[v].size() && e[v][k].point < e[u][j].point; k++);
if (k >= e[v].size()) break;
if (e[u][j].point == e[v][k].point)
common.push_back(std::make_pair(j, k)), j++, k++;
} for (int j = ; j < common.size(); j++)
{
int w = e[u][common[j].first].point;
int c1, c2, c3;
e[u][i].tri++;
e[u][common[j].first].tri++;
e[v][common[j].second].tri++;
c1 = e[u][i].color;
c2 = e[u][common[j].first].color;
c3 = e[v][common[j].second].color;
tri[u]++, tri[v]++, tri[w]++;
if (c1 != c2 && c2 != c3 && c3 != c1)
ans -= tmp - ;
else
{
ans -= tmp;
if (c1 == c2) tri0[u]++;
if (c1 == c3) tri0[v]++;
if (c2 == c3) tri0[w]++;
}
}
}
//type1
for (int u = ; u <= n; u++)
for (int i = ; i < e[u].size(); i++)
{
int v = e[u][i].point;
uint cnt = n - deg[u] - deg[v] + e[u][i].tri;
ans -= cnt * (tmp - (m - ) * (m - ));
}
//type2
for (int i = ; i < p; i++)
if (deg[a[i].u] >= deg[a[i].v])
add_edge(a[i].u, a[i].v, a[i].color);
else
add_edge(a[i].v, a[i].u, a[i].color);
for (int i = ; i <= n; i++)
{
std::sort(e[i].begin(), e[i].end(), cmp_color);
uint cnt = comb_2(deg[i]) - tri[i];
ans -= cnt * (tmp - (m - ));
cnt = ;
for (int j = ; j < e[i].size(); j++)
if (e[i][j].color == e[i][j - ].color)
cnt++;
else
{
ans -= comb_2(cnt) * (m - );
cnt = ;
}
ans -= comb_2(cnt) * (m - );
ans += tri0[i] * (m - );
} if (m < ) ans = ;
printf("%u\n", ans);
} return ;
} edge_list::edge_list(int _point, int _color)
{
point = _point;
color = _color;
tri = ;
}
bool edge_list::operator < (const edge_list & other) const
{
return point < other.point;
}
void edge_tuple::get()
{
u = getint();v = getint();
color = getint();
} int getint()
{
int num = ;
char ch;
do ch = getchar();
while (ch < '' || ch > '');
do num = num * + ch - '', ch = getchar();
while (ch >= '' && ch <= '');
return num;
}
uint comb_2(int n)
{
uint f = ;
if (n < )
return ;
if (n & )
f = n - , f *= n;
else
f = n , f *= n - ;
return f;
}
uint comb_3(int n)
{
uint f = , a = n, b = n - , c = n - ;
if (n < )
return ;
if (a % == ) a /= ;
else if (b % == ) b /= ;
else c /= ;
if (a & ) b = ;
else a = ;
f = a * b * c;
return f;
}
void add_edge(int u, int v, int color)
{
e[u].push_back(edge_list(v, color));
}
void init(int n)
{
for (int i = ; i <= n; i++)
e[i].clear();
memset(tri, , sizeof(tri));
memset(tri0, , sizeof(tri0));
memset(deg, , sizeof(deg));
}
bool cmp_color(const edge_list & a, const edge_list & b)
{
return a.color < b.color;
}
10.24afternoon清北学堂刷题班的更多相关文章
- 2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结
成绩:满分300,我得了200, 1:90//前两个题目都是模拟,没用到什么其他算法,第一题有可能少考虑了一点细节 2:100 3:10//感觉是个DP,但是毫无思路,只打了个普通背包,10分而已. ...
- 【清北学堂2018-刷题冲刺】Contest 7
Task 1:小奇采药 [问题描述] 小奇是只天资聪颖的喵,他的梦想是成为世界上最伟⼤的医师. 为此,他想拜喵星球最有威望的医师为师. 医师为了判断他的资质,给他出了⼀个难题. 医师把他带到⼀ ...
- 【清北学堂2018-刷题冲刺】Contest 6
Task 1:子集 [问题描述] 若一个集合S中任意两个元素x和y,都满足x⊕y<min(x, y) ,则称集合S是"好的".其中⊕为按位异或运算符.现在给定一个大小为n ...
- 【清北学堂2018-刷题冲刺】Contest 5
这三个题写了一天半,第一个题写了大概一整天.出题人劝我从后往前写,我不听,结果T1想了+调了一天QWQWQ Task 1:序列 [问题描述] 定义一个"好的序列"为一个长度为M ...
- 【清北学堂2018-刷题冲刺】Contest 4
Task 1:序列 [问题描述] 小H原本有一个由连续的正整数组成的序列,如{4,5,6}或{10,11,12,13,14,15,16},但是她最近睡眠不足,只能记得其中的一些数字.她想知道,她最少 ...
- 【清北学堂2018-刷题冲刺】Contest 2
这场比赛的T1相当智熄.由于至今无法理解题意,我只能解出前20分.诸位dalao谁能比较好地理解题意(独立性)的,请联系我,不胜感激. 在此本蒟蒻只能贴上题面: Task 1:选举 [问题描述] ...
- 【清北学堂2018-刷题冲刺】Contest 1
Task 1:最小公倍数 输入n,求n与246913578的最小公倍数. 结果对1234567890取模. [样例输入] 3 [样例输出] 246913578 [数据规模和约定] 对于30%的数据 ...
- 【清北学堂2018-刷题冲刺】Contest 8
Task 1:关联点 [问题描述] ⼆叉树是⼀种常用的数据结构,⼀个⼆叉树或者为空,或者由根节点.左⼦树.右⼦树构成,其中左⼦树和右⼦树都是⼆叉树. 每个节点a 可以存储⼀个值val. 显然,如果 ...
- 清北考前刷题day1下午好
水题(water) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK出了道水题. 这个水题是这样的:有两副牌,每副牌都有n张. 对于第一副牌的每张牌长和宽 ...
随机推荐
- 字符串String对象构造方法的创建和直接赋值的区别
/* * 通过构造方法创建的字符串对象和直接赋值方式创建的字符串对象有什么区别呢? * 区别是:通过构造方法创建的字符串对象是在堆内存.通过赋值创建的字符串对象是在方法区的常量池 * * == * 基 ...
- Linux下汇编语言学习笔记32 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- hdu - 1195 Open the Lock (bfs) && hdu 1973 Prime Path (bfs)
http://acm.hdu.edu.cn/showproblem.php?pid=1195 这道题虽然只是从四个数到四个数,但是状态很多,开始一直不知道怎么下手,关键就是如何划分这些状态,确保每一个 ...
- codevs——1019 集合论与图论
1019 集合论与图论 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 集合论与图论对于小松来说 ...
- java web 验证码 第一次不正确的问题,解决方案
首先是form表单 ,获取图片验证码 然后使用js 去服务器验证 问题: 第一次明明输入正确 ,确验证不了??那是因为你在form表单发起请求 和 ajax 发起的请求 地址 中 一个使用127. ...
- 第一个Spring程序(DI的实现)
一,依赖注入:Dependency Injection(DI)与控制反转(IoC),不同角度但是同一个概念.首先我们理解一点在传统方式中我们使用new的方式来创建一个对象,这会造成对象与被实例化的对象 ...
- Spring基础入门(三)
一.Spring的jdbcTemplate操作 (1)Spring是一站式框架,对于javaee三层,每一层都有解决技术. web层:springMVC service:spring的ioc dao层 ...
- Ubuntu 16.04下减小/释放/清理VirtualBox虚拟硬盘文件的大小
一般在VirtualBox中安装Windows,然后用无缝模式进行某些特定软件的使用. 而VirtualBox的虚拟硬盘会越用越大,并且VirtualBox没有自带清理工具,相比VMware来说,VM ...
- react 服务器端渲染 ssr 中 localstorage/history/window is not defined 解决方案
1.原因 ssr 会在后端执行组件的 componentWillMount 以及在它这个生命周期之前的生命周期 也就是说 ssr 阶段是不会执行 componentDidMount 方法的 当你在 c ...
- TCP/IP协议族-----22、万维网和HTTP