/*
这是什么题...
*/
#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清北学堂刷题班的更多相关文章

  1. 2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结

    成绩:满分300,我得了200, 1:90//前两个题目都是模拟,没用到什么其他算法,第一题有可能少考虑了一点细节 2:100 3:10//感觉是个DP,但是毫无思路,只打了个普通背包,10分而已. ...

  2. 【清北学堂2018-刷题冲刺】Contest 7

    Task 1:小奇采药 [问题描述]  小奇是只天资聪颖的喵,他的梦想是成为世界上最伟⼤的医师.  为此,他想拜喵星球最有威望的医师为师.  医师为了判断他的资质,给他出了⼀个难题.  医师把他带到⼀ ...

  3. 【清北学堂2018-刷题冲刺】Contest 6

    Task 1:子集 [问题描述]  若一个集合S中任意两个元素x和y,都满足x⊕y<min⁡(x, y) ,则称集合S是"好的".其中⊕为按位异或运算符.现在给定一个大小为n ...

  4. 【清北学堂2018-刷题冲刺】Contest 5

     这三个题写了一天半,第一个题写了大概一整天.出题人劝我从后往前写,我不听,结果T1想了+调了一天QWQWQ Task 1:序列 [问题描述]  定义一个"好的序列"为一个长度为M ...

  5. 【清北学堂2018-刷题冲刺】Contest 4

    Task 1:序列 [问题描述]  小H原本有一个由连续的正整数组成的序列,如{4,5,6}或{10,11,12,13,14,15,16},但是她最近睡眠不足,只能记得其中的一些数字.她想知道,她最少 ...

  6. 【清北学堂2018-刷题冲刺】Contest 2

     这场比赛的T1相当智熄.由于至今无法理解题意,我只能解出前20分.诸位dalao谁能比较好地理解题意(独立性)的,请联系我,不胜感激.  在此本蒟蒻只能贴上题面: Task 1:选举 [问题描述] ...

  7. 【清北学堂2018-刷题冲刺】Contest 1

    Task 1:最小公倍数  输入n,求n与246913578的最小公倍数.  结果对1234567890取模. [样例输入] 3 [样例输出] 246913578 [数据规模和约定] 对于30%的数据 ...

  8. 【清北学堂2018-刷题冲刺】Contest 8

    Task 1:关联点 [问题描述]  ⼆叉树是⼀种常用的数据结构,⼀个⼆叉树或者为空,或者由根节点.左⼦树.右⼦树构成,其中左⼦树和右⼦树都是⼆叉树. 每个节点a 可以存储⼀个值val.  显然,如果 ...

  9. 清北考前刷题day1下午好

    水题(water) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK出了道水题. 这个水题是这样的:有两副牌,每副牌都有n张. 对于第一副牌的每张牌长和宽 ...

随机推荐

  1. Webdriver测试脚本2(控制浏览器)

    Webdriver提供了操作浏览器的一些方法,例如控制浏览器的大小.操作浏览器前进和后退等. 控制浏览器窗口大小 有时候我们希望能以某种浏览器尺寸打开,让访问的页面在这种尺寸下运行.例如可以将浏览器设 ...

  2. codevs 3971 航班

    题目描述 Description B 国有N 座城市,其中1 号是这座国家的首都. N 座城市之间有M 趟双向航班.i 号点的转机次数定义为:从1 号点到i ,最少需要转机几 次.如果1 根本无法到达 ...

  3. 【转】Intellij IDEA 快捷键大全

    IntelliJ Idea 常用快捷键列表 Ctrl+Shift + Enter,语句完成“!”,否定完成,输入表达式时按 “!”键Ctrl+E,最近的文件Ctrl+Shift+E,最近更改的文件Sh ...

  4. Ubuntu 16.04重启输入法

    一般使用搜狗输入法,但是偶尔不太稳定会挂掉,但是可以通过以下脚本重启: pidof fcitx | xargs kill pidof sogou-qimpanel | xargs kill nohup ...

  5. 学习swift从青铜到王者之Swift集合数据类型03

    1 数组的定义 var array1 = [,,,] var array2: Array = [,,,] var array3: Array<Int> = [,,,] var array4 ...

  6. javascript 时间格式(很方便的原生函数)

    原文:http://www.cnblogs.com/yjf512/p/3796229.html --------------------- <html xmlns="http://ww ...

  7. 007 Vlan config

    sw0(config)#vlan 2 sw0(config-vlan)#name Sales sw0(config-vlan)#vlan 3 sw0(config-vlan)#name Tech sw ...

  8. kvm虚拟化网络管理

    Linux Bridge 网桥管理 VM2 的虚拟网卡 vnet1 也连接到了 br0 上. 现在 VM1 和 VM2 之间可以通信,同时 VM1 和 VM2 也都可以与外网通信 # Vlan LAN ...

  9. cocos2d-x2.2.5走四棋儿源代码“开源”

    尊重开发人员的劳动成果.转载请注明From郝萌主 游戏简单介绍: 一款益智棋类游戏,通过两枚棋子对上敌方的一枚棋子便可击杀对方. 游戏界面精美简洁,游戏规则简单明了,AI聪明有趣. 人人对战,人机对战 ...

  10. Python爬虫(一):基本概念

    网络爬虫的定义          网络爬虫(Web Spider.又被称为网页蜘蛛.网络机器人,又称为网页追逐者),是一种依照一定的规则,自己主动的抓取万维网信息的程序或者脚本.另外一些不常使用的名字 ...