HDU-6608
/***
1006 Fansblog HDU-6608
题意:给一个1e9-1e14的质数p,求一个Q!mod p的值,Q为小于p的最大质数
思路:威尔逊定理变形得到x!%y=1/(y-x-1)%mod;
y,x为2个连续的素数且y>x;由素数分布密度可知,y与x不会太远。
中间还涉及逆元需要处理。
***/
#include
using namespace std;
#define ll long long
ll p;
void exgcd(ll a, ll b, ll &x, ll &y) {
if (b == 0) {
x = 1;y = 0;
} else {
exgcd(b, a%b, y, x);
y -= (a/b) * x;
}
}
ll inv(ll a) {
ll x,y;
exgcd(a,p,x,y);
x=(x%p+p)%p;
printf("%lld\n",x);
}
bool judge(ll x)
{
for(ll i=2;i*i<=x;i++)
{
if(x%i==0)return 0;
}
return 1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&p);
for(ll i=p-1;;i--)
{
if(judge(i))
{
ll ind=p-i-1;
ll res=1ll;
for(ll i=1;i<=ind;i++)res=res*i,res%=p;
inv(res);
break;
}
}
}
return 0;
}
HDU-6609
/*****
1007 Find the answer HDU 6609
题目大意:n个数,对于前i-1个数,剔除多少个数就能使剩余的数求和小于等于m-a[i]
解题思路:将n个数进行离散化,线段树维护一个sum表示区间和,一个num表示当前叶子节点之前有几个比他还
小的数,然后对于每次询问,查询m-a[i],如果大于当前sum,则遍历左子树跟右子树,否则查询值-=sum,然
后return,直到遇到叶子节点,并且叶子节点sum>当前查询值,返回该节点num-1,表示需要剔除
i-1-(num-1)个数,然后把a[i]加到树中,更新num即可
总结:比赛当时用优先队列去写这个题,由于极限样例需要多次push跟pop导致超时
*****/
#include
using namespace std;
#define ll long long
const ll maxn = 2e6+5;
bool flag;
struct TREE
{
#define lson rt<<1
#define rson rt<<1|1
struct Tree{
ll l,r,num,lazy;
ll sum;
ll mid(){ return (l+r)>>1; }
ll len(){ return r-l+1; }
}tree[maxn<<2];
ll ans;
void pushdown(ll rt){
if(tree[rt].lazy){
tree[lson].lazy += tree[rt].lazy;
tree[rson].lazy += tree[rt].lazy;
tree[lson].num += tree[rt].lazy;
tree[rson].num += tree[rt].lazy;
tree[rt].lazy = 0;
}
}
void pushup(ll rt){
tree[rt].sum = tree[lson].sum + tree[rson].sum;
}
void build(ll l, ll r, ll rt){
tree[rt].l=l;tree[rt].r=r;
tree[rt].sum = tree[rt].num = tree[rt].lazy = 0;
if(l == r) return ;
ll m = tree[rt].mid();
build(l,m,lson);
build(m+1,r,rson);
}
void update_sum(ll val, ll pos, ll rt){
if(tree[rt].l == tree[rt].r && tree[rt].l == pos){
tree[rt].sum = val;
return ;
}
pushdown(rt);
//if(tree[rt].l == tree[rt].r) return ;
ll m = tree[rt].mid();
if(pos <= m) update_sum(val, pos, lson);
else update_sum(val, pos, rson);
pushup(rt);
}
void update_num(ll val, ll l, ll r, ll rt){
if(tree[rt].l == l && tree[rt].r == r){
tree[rt].lazy += val;
tree[rt].num += val;
return ;
}
if(tree[rt].l == tree[rt].r) return ;
pushdown(rt);
ll m = tree[rt].mid();
if(r <= m) update_num(val, l, r, lson);
else if(l > m) update_num(val, l, r, rson);
else {
update_num(val, l, m, lson);
update_num(val, m+1, r, rson);
}
}
ll w;
void query(ll l,ll r,ll rt){
if(!flag) return ;
if(tree[rt].l == tree[rt].r && tree[rt].sum > w && flag){
ans = tree[rt].num -1;
flag = false;
return ;
}
pushdown(rt);
ll m = tree[rt].mid();
if(w < tree[rt].sum){
query(l,m,lson);
query(m+1,r,rson);
}
else{
w -= tree[rt].sum;
return ;
}
}
}myTree;
struct node
{
ll val,pos,i;
}a[maxn];
ll n,k;
bool cmp1(node x, node y)
{
return x.val
HDU-6611
/*****
1009 K Subsequence HDU 6611
题意:给定一个n和k,n表示接下来的序列长度,给定序列a,我们可以从这个序列中拿出k个单调不减的子序
列,每次拿了之后可以获得这个子序列的权值和,并且再这之后不能再拿之前拿过的这些数了,求拿了k次之后
得到的最大权值和。
思路:最小费用最大流(也可以最大费用最大流),首先建立源点s和超级源点ss,ss指向s,流为k,花费为
0;然后输入序列的每个ai,将ai割为ai0,ai1两个点,ai0指向ai1,流为1,花费为-ai(用最大费用最大流
的话就改为ai);然后将源点指向每个ai0,流为1,花费为0;将每个ai1指向汇点t,流为1,花费为0;然后
按最长不下降子序列的概念加边:若i>j(1<=i,j<=n),且ai>=aj,aj1指向ai0,流为1,花费为0,最后
MCMF求最小费用最大流(最后的值要取反)。
*****/
#include
#define memset0(arr) memset(arr, 0, sizeof(arr))
#define il inline
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair pii;
const int maxn = 1e4;
const int INF = 0x7fffffff;
const int mod = 1e9 + 7;
const double eps = 1e-7;
const double Pi = acos(-1.0);
il int read_int() {
char c;
int ret = 0, sgn = 1;
do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
if (c == '-') sgn = -1; else ret = c - '0';
while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
return sgn * ret;
}
il ll read_ll() {
char c;
ll ret = 0, sgn = 1;
do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
if (c == '-') sgn = -1; else ret = c - '0';
while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
return sgn * ret;
}
il ll quick_pow(ll base, ll index) {
ll res = 1;
while (index) {
if (index & 1)res = res * base % mod;
base = base * base % mod;
index >>= 1;
}
return res;
}
struct edge {
int to, capacity, cost, rev;
edge() {}
edge(int to, int _capacity, int _cost, int _rev) :to(to), capacity(_capacity), cost(_cost), rev(_rev) {}
};
struct Min_Cost_Max_Flow {
int V, H[maxn + 5], dis[maxn + 5], PreV[maxn + 5], PreE[maxn + 5];
vector G[maxn + 5];
void Init(int n) {
V = n;
for (int i = 0; i <= V; ++i)G[i].clear();
}
void add(int from, int to, int cap, int cost) {
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
int Min_cost_max_flow(int s, int t, int f, int& flow) {
int res = 0; fill(H, H + 1 + V, 0);
while (f) {
priority_queue , vector >, greater > > q;
fill(dis, dis + 1 + V, INF);
dis[s] = 0; q.push(pair(0, s));
while (!q.empty()) {
pair now = q.top(); q.pop();
int v = now.second;
if (dis[v] < now.first)continue;
for (int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if (e.capacity > 0 && dis[e.to] > dis[v] + e.cost + H[v] - H[e.to]) {
dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
PreV[e.to] = v;
PreE[e.to] = i;
q.push(pair(dis[e.to], e.to));
}
}
}
if (dis[t] == INF)break;
for (int i = 0; i <= V; ++i)H[i] += dis[i];
int d = f;
for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity);
f -= d; flow += d; res += d*H[t];
for (int v = t; v != s; v = PreV[v]) {
edge& e = G[PreV[v]][PreE[v]];
e.capacity -= d;
G[v][e.rev].capacity += d;
}
}
return res;
}
int Max_cost_max_flow(int s, int t, int f, int& flow) {
int res = 0;
fill(H, H + 1 + V, 0);
while (f) {
priority_queue > q;
fill(dis, dis + 1 + V, -INF);
dis[s] = 0;
q.push(pair(0, s));
while (!q.empty()) {
pair now = q.top(); q.pop();
int v = now.second;
if (dis[v] > now.first)continue;
for (int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if (e.capacity > 0 && dis[e.to] < dis[v] + e.cost + H[v] - H[e.to]) {
dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
PreV[e.to] = v;
PreE[e.to] = i;
q.push(pair(dis[e.to], e.to));
}
}
}
if (dis[t] == -INF)break;
for (int i = 0; i <= V; ++i)H[i] += dis[i];
int d = f;
for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity);
f -= d; flow += d;
res += d*H[t];
for (int v = t; v != s; v = PreV[v]) {
edge& e = G[PreV[v]][PreE[v]];
e.capacity -= d;
G[v][e.rev].capacity += d;
}
}
return res;
}
};
int n, k, s1, s2, t, flow, aa[maxn + 5];
Min_Cost_Max_Flow MCMF;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
int s=0,t=2*n+2;
MCMF.Init(t);
for(int i=1;i<=n;i++)
{
scanf("%d",&aa[i]);
MCMF.add(i,i+n,1,-aa[i]);
MCMF.add(2*n+1,i,1,0);
MCMF.add(i+n,2*n+2,1,0);
}
MCMF.add(s,n*2+1,k,0);
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(aa[j]>=aa[i])//&&F[j]==F[i]+1
{
MCMF.add(i+n,j,1,0);
}
}
}
int x=0;
cout<<-MCMF.Min_cost_max_flow(s,t,INF,x)<