今日打卡:洛谷:P1344 [USACO4.4] 追查坏牛奶 Pollutant Control/P1361 小M的作物/P1393 Mivik 的标题

前两天断签了~~~好在洛谷对我好,网开一面。虽然打卡天数没清零,但还是保持在9天。(至少没掉)为了补回前两天的题目,加上今天的题目,一共是三题。这是今天的幸运签:

今天的还不错吧,我天天都写洛谷日报(观众:前两天你不是没写吗?)但是今天我考了两场试成绩都不理想啊~~~

好啦~要题解的看这里:

P1344 [USACO4.4] 追查坏牛奶 Pollutant Control:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
#define int long long 
const int maxn = 10005;
const int maxm = 2e5 + 5;
const int inf = 999999999;
const int mod = 1007;
inline int read()
{
  int ans = 0,op = 1;
  char ch = getchar();
  while(ch < '0' || ch > '9')
    {
      if(ch == '-') op = -1;
      ch = getchar();
    }
  while(ch >= '0' && ch <= '9')
    {
      (ans *= 10) += ch - '0';
      ch = getchar();
    }
  return ans * op;
}
struct egde
{
  int to,cost,next,other;
}e[maxm];
int fir[maxn],alloc;
void adde(int u,int v,int w)
{
  e[++alloc].next = fir[u];
  fir[u] = alloc;
  e[alloc].to = v;
  e[alloc].cost = w * mod + 1;
  e[alloc].other = alloc + 1;
  swap(u,v);
  e[++alloc].next = fir[u];
  fir[u] = alloc;
  e[alloc].to = v;
  e[alloc].cost = 0;
  e[alloc].other = alloc - 1;
}
int n,m,s,t;
int cnt,ans;
bool vis[maxn];
int dep[maxn];
bool bfs(int s,int t)
{
  memset(dep,0,sizeof(dep));
  queue<int> q;
  dep[s] = 1;
  q.push(s);
  while(q.size())
    {
      int u = q.front();
      q.pop();
      for(int i = fir[u];i;i = e[i].next)
    {
      int v = e[i].to,c = e[i].cost;
      if(c > 0 && dep[v] == 0 && vis[i] == 0)
        {
          dep[v] = dep[u] + 1;
          q.push(v);
        }
    }
    }
  //for(int i = 1;i <= n;i++) printf("%d %d\n",i,dep[i]);
  if(dep[t]) return 1;
  else return 0;
}
int find(int u,int f)//在u点,要解决值为f的流量
{
  //printf("%d %d\n",u,f);
  if(u == t) return f;
  int curflow = 0,t = 0;
  for(int i = fir[u];i;i = e[i].next)
    {
      int v = e[i].to,c = e[i].cost;
      if(c > 0 && dep[v] == dep[u] + 1 && curflow < f && vis[i] == 0)
    {
      t = find(v,min(c,f - curflow));
      curflow += t;
      e[i].cost -= t;
      e[e[i].other].cost += t;
    }
    }
  return curflow;
}
main()
{
  n = read(),m = read();
  for(int i = 1;i <= m;i++)
    {
      int u = read(),v = read(),w = read();
      adde(u,v,w);
    }
  s = 1,t = n;
  while(bfs(s,t))
    ans += find(s,inf);
  printf("%d ",ans / mod);
  printf("%d",ans % mod);
}

P1361 小M的作物:

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#define M 5000000
#define N 2000000 
#define INF 0x3f3f3f3f
#define re register
#define int long long//邪教宏定义
#define _ 0
#define drep(k ,l ,r) for(re int k = r ; k >= l ; -- k )
#define rep(k ,l ,r) for(re int k = l ; k <= r ; ++ k)
using namespace std;
int n ,m ,u ,v ,w ,head[N] ,tot = 1 ,s ,t;
int cap ,cnt ,c1 ,c2 ,numb ,pax1 ,pax2 ,tmp;
int high[N] ,gap[N] ,extra[N];//三个数组分别是高度,超额流量,gap优化
bool vis[N];
queue<int> que;
stack<int> sta;
struct edge {
   int next ,to ,w;
} e[M];
int read() {
   char cc = getchar() ; int cn = 0 ,flus = 1;
   while(cc < '0' || cc > '9') {if(cc == '-') flus = - flus ; cc = getchar() ; }
   while(cc >= '0' && cc <= '9') cn = cn * 10 + cc - '0' ,cc = getchar();
   return flus * cn;
}
void add_sapr(int u ,int v ,int w) {
   e[++tot].next = head[u];
   head[u] = tot;
   e[tot].to = v;
   e[tot].w = w;
}
void add(int u ,int v ,int w) {
   add_sapr(u ,v ,w) ,add_sapr(v ,u ,0);//建边
}
bool bfs() {//注意这里的bfs是反向bfs,但同样也是判断图的连通性
   rep(i ,0 ,N - 1) high[i] = INF;
   que.push(t) ,high[t] = 0;
   while(!que.empty()) {
       u = que.front() ,que.pop();
       for(int i = head[u] ; i ; i = e[i].next) 
           if(e[i ^ 1].w && high[e[i].to] > high[u] + 1) high[e[i].to] = high[u] + 1 ,que.push(e[i].to) ;
   }
   return high[s] != INF;
}
struct cmp {
   bool operator()(int a ,int b) const { return high[a] < high[b]; }
};//重载运算符
priority_queue<int ,vector<int> ,cmp> pri_que;
bool push(int u) {//尽可能多推送超额流
   for(int i = head[u] ; i ; i = e[i].next) {
       const int wi = e[i].w;
       if(!wi || high[u] != high[e[i].to] + 1) continue;
       int minn = min(wi ,extra[u]);
       extra[u] -= minn ,extra[e[i].to] += minn ,e[i].w -= minn ,e[i ^ 1].w += minn;
       if(e[i].to != s && e[i].to != t && !vis[e[i].to]) pri_que.push(e[i].to) ,vis[e[i].to] = 1;// 推送之后,v 必然溢出,则入堆,等待被推送
       if(!extra[u]) return 0;//没了就返回
   }
   return 1;
}
void relabel(int u) {//重新贴高度标签
   high[u] = INF;
   for(int i = head[u] ; i ; i = e[i].next) 
       if(e[i].w) high[u] = min(high[u] ,high[e[i].to]);
   ++high[u];
}
int hlpp() {
   if(!bfs()) return 0;
   high[s] = n;
   rep(i ,0 ,N - 1) if(high[i] != INF) ++gap[high[i]];//gap优化
   for(int i = head[s] ; i ; i = e[i].next) {
       const int wi = e[i].w;
       if(!wi) continue;
       extra[s] -= wi ,extra[e[i].to] += wi ,e[i].w -= wi ,e[i ^ 1].w += wi;
       if(e[i].to != s && e[i].to != v && !vis[e[i].to]) pri_que.push(e[i].to) ,vis[e[i].to] = 1;
   }
   while(!pri_que.empty()) {
       int u = pri_que.top();
   	pri_que.pop() ,vis[u] = 0;
       while(push(u)) {
           if(!(--gap[high[u]])) //gap优化(如果 u 结点原来所在的高度没有结点了,相当于出现断层)
   			rep(i ,1 ,n) 
   				if(i != s && i != t && high[i] > high[u] && high[i] < n + 1) high[i] = n + 1;
           relabel(u);
           ++gap[high[u]];
       }
   }
   return extra[t];//返回超额流
}
signed main() {
   n = read();t = n + 1;
   rep(i ,1 ,n) cap = read() ,add(s ,i ,cap) ,cnt += cap;
   rep(i ,1 ,n) cap = read() ,add(i ,t ,cap) ,cnt += cap;
   m = read();pax1 = n + 2 ,pax2 = n + 3;
   rep(i ,1 ,m) {
       numb = read() ,c1 = read() ,c2 = read();
       cnt = cnt + c1 + c2;
       add(s ,pax1 ,c1) ,add(pax2 ,t ,c2);
       rep(i ,1 ,numb) tmp = read() ,add(pax1 ,tmp ,INF) ,add(tmp ,pax2 ,INF);
       pax1 += 2 ,pax2 += 2;//虚点更新
   }
   printf("%lld" ,cnt - hlpp());//答案即为总和减去最小割
   return ~~(0^_^0);
}

P1393 Mivik 的标题:
 

#include<bits/stdc++.h>
#define ll long long
#define il inline
#define pn putchar('\n')
#define maxint 2147483647
#define min(x,y) (x<y?x:y)
#define max(x,y) (x>y?x:y)
#define maxn 1000005
#define mod 998244353
#define I 86583718LL
#define g 3
#define int ll
using namespace std;
il void upd(int &x,int y)
{
    x+=y;
    if(x>=mod)x-=mod;
    if(x<0)x+=mod;
}
il int ksm(int x,int y)
{
    int ret=1;
    while(y)
    {
        if(y&1)ret=ret*x%mod;
        x=x*x%mod,y>>=1;
    }
    return ret;
}
namespace polynomial
{
    int gn[maxn],gi[maxn],rev[maxn],iv[maxn];
    il void init()
    {
        for(int i=1;i<=1e6;i<<=1)
            gn[i]=ksm(g,(mod-1)/i),gi[i]=ksm(gn[i],i-1);
        iv[0]=iv[1]=1;
        for(int i=2;i<=1e6;i++)
            iv[i]=(mod-mod/i)*iv[mod%i]%mod;
    }
    il int getn(int n)
    {
        return 1<<(int)ceil(log2(n));
    }
    il void getrev(int n)
    {
        for(int i=0;i<n;i++)
            rev[i]=(rev[i>>1]>>1)|((i&1)?n>>1:0);
    }
    il void print(int *a,int n)
    {
        for(int i=0;i<n;i++)
            printf("%lld ",a[i]);
        pn;
    }
    il void add(int *a,int *b,int n)
    {
        for(int i=0;i<n;i++)
            upd(a[i],b[i]);
    }
    il void px(int *a,int *b,int n)
    {
        for(int i=0;i<n;i++)
            a[i]=a[i]*b[i]%mod;
    }
    il void cpy(int *a,int *b,int n)
    {
        for(int i=0;i<n;i++)
            a[i]=b[i];
    }
    il void clr(int *a,int n)
    {
        for(int i=0;i<n;i++)
            a[i]=0;
    }
    il void NTT(int *a,int n,int ty=1)
    {
        for(int i=0;i<n;i++)
            if(rev[i]<i)
                swap(a[i],a[rev[i]]);
        for(int i=1;i<n;i<<=1)
        {
            int y=ty==1?gn[i<<1]:gi[i<<1];
            for(int j=0;j<n;j+=i<<1)
            {
                int x=1;
                for(int k=j;k<j+i;k++,x=x*y%mod)
                {
                    int l=a[k],r=x*a[k+i]%mod;
                    a[k]=l+r,a[k+i]=l-r;
                    a[k]=a[k]>=mod?a[k]-mod:a[k];
                    a[k+i]=a[k+i]<0?a[k+i]+mod:a[k+i];
                }
            }
        }
        if(ty==-1)
        {
            for(int i=0;i<n;i++)
                a[i]=a[i]*iv[n]%mod;
        }
    }
    il void ch(int *a,int* F,int* G,int n)
    {
        getrev(n);
        NTT(F,n);
        NTT(G,n);
        for(int i=0;i<n;i++)
            a[i]=F[i]*G[i]%mod;
        NTT(a,n,-1);
    }
    static int tni[maxn],tni2[maxn];
    il void bni(int *a,int *b,int n)
    {
        if(n==1)
        {
            b[0]=ksm(a[0],mod-2);
            return;
        }
        cpy(tni2,a,n),cpy(tni,b,n);
        ch(tni,tni,tni2,n);
        clr(tni,n>>1);
        cpy(tni2,b,n);
        ch(tni,tni,tni2,n);
        for(int i=n>>1;i<n;i++)
            b[i]=tni[i]?mod-tni[i]:0;
    }
    il void ni(int *a,int *b,int n)
    {
        n=getn(n<<1);
        clr(b,n);
        for(int len=1;len<n;len<<=1)
            bni(a,b,len);
    }
}
using namespace polynomial;
int n,k,m;
int a[maxn],F[maxn],G[maxn],nex[maxn];
signed main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    init();
    scanf("%lld%lld%lld",&n,&k,&m);
    for(int i=1;i<=m;i++)
        scanf("%lld",&a[i]);
    for(int i=2,j=0;i<=m;i++)
    {
        while(j&&a[j+1]!=a[i])
            j=nex[j];
        if(a[j+1]==a[i])
            j++;
        nex[i]=j;
    }
    for(int i=m;i;i=nex[i])
        F[m-i]++;
    ni(F,G,n+1);
    for(int i=n;i>=m;i--)
        G[i]=G[i-m];
    for(int i=0;i<m;i++)
        G[i]=0;
    G[0]=1;
    G[1]=(mod-k+G[1])%mod;
    ni(G,F,n+1);
    printf("%lld",(ksm(k,n)-F[n]+mod)%mod*ksm(k,n*(mod-2))%mod);
    return 0;
}

记得三连哟!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值