zoukankan      html  css  js  c++  java
  • 湖南集训day8

    难度:☆☆☆☆☆☆☆

    /*
    可以先考虑一维,可知 模k意义下相同的前缀和任意两个相减都是k的倍数
    问题等价于统计前缀何种模k相同的数的对数。
    多维的时候二维前缀和,压行或者压列,n^3可以解决。 
    */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define K 1000007
    #define N 400
    
    using namespace std;
    typedef long long LL;
    int f[K],s[N][N];
    
    int main()
    {
        freopen("rally.in", "r", stdin);
        freopen("rally.out", "w", stdout);
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            {
                scanf("%d",s[i]+j);
                s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
                if (s[i][j]<0) s[i][j]+=k;
                if (s[i][j]>0) s[i][j]%=k;
            }
        LL ans=0;
        f[0]=1;
        for (int l=1;l<=m;l++)
            for (int r=l;r<=m;r++)
            {
                for (int i=1;i<= n;i++)
                {
                    int sum=s[i][r]-s[i][l-1];
                    if (sum<0) sum+=k;
                    ans+=f[sum];f[sum]++;
                }
                for (int i=1;i<=n;i++)
                {
                    int sum=s[i][r]-s[i][l-1];
                    if (sum<0) sum+=k;f[sum]--;
                }
            }
        printf("%lld
    ",ans);
        return 0;
    }

    /*
    树形dp可做,好难好难的样子
    考虑贪心 暗点的深度排序,每次拿出未被更新的最深的点把他的k级父亲标记 
    然后用这个点向外扩展更新每个点距离标记点的距离 
    正确性显然 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define N 100007
    
    using namespace std;
    int head[N],q[N],f[N],fa[N];
    int n,m,ans,cnt,K,t;
    struct edge{
        int u,v,net;
    }e[N<<1];
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    inline void add(int u,int v)
    {
        e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
    }
    
    void bfs()
    {
        int he=1,ta=1;
        q[ta++]=1;fa[1]=1;
        while(he<=ta)
        {
            int u=q[he++];;
            for(int i=head[u];i;i=e[i].net)
            {
                int v=e[i].v;
                if(!fa[v])
                {
                    fa[v]=u;q[ta++]=v;
                } 
            }
        }
    }
    
    void update(int u)
    {
        if(!f[u]) return;
        for(int i=head[u];i;i=e[i].net)
        {
            int v=e[i].v;
            if(f[v]<f[u]-1)
              f[v]=f[u]-1,update(v);
        }
    }
    
    int main()
    {
        freopen("general.in", "r", stdin);
        freopen("general.out", "w", stdout);
        int x,y;
        n=read();K=read();t=read();
        for(int i=1;i<n;i++)
        {
            x=read();y=read();
            add(x,y);add(y,x);
        }
        bfs();
        memset(f,-1,sizeof f);
        for(int i=n;i;i--)
        {
            if(f[q[i]]==-1)
            {
                int j=q[i];
                for(int k=K;k;k--) j=fa[j];
                ans++;f[j]=K;
                update(j);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }

    这道题简直了,妙不可言!!!!!!!!!!!!!!

    前方高能题解

    可是...那个“比较简单的状压dp”怎么写啊......

    gg

    std

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef pair<int, int> pii;
    #define fir first
    #define sec second
    #define INF 0x3f3f3f3f
    #define MAXN 40005
    #define TOP 18
    
    int n, K, m, cnt = 0;
    bool a[MAXN];
    int dis[18][MAXN], b[70];
    pii p[18];
    
    queue <int> q;
    
    void bfs(pii st)
    {
    	for (int i = 0; i < MAXN; i++) dis[st.fir][i] = INF;
    	q.push(st.sec);
    	dis[st.fir][st.sec] = 0;
    	while (!q.empty())
    	{
    		int x = q.front();
    		q.pop();
    		for (int i = 1; i <= m; i++)
    		{
    			if (x - b[i] >= 0 && dis[st.fir][x - b[i]] > dis[st.fir][x] + 1)
    			{
    				dis[st.fir][x - b[i]] = dis[st.fir][x] + 1;
    				q.push(x - b[i]);
    			}
    			if (x + b[i] <= n && dis[st.fir][x + b[i]] > dis[st.fir][x] + 1)
    			{
    				dis[st.fir][x + b[i]] = dis[st.fir][x] + 1;
    				q.push(x + b[i]);
    			}
    		}
    	}
    }
    
    int dp[1 << 18];
    
    int solve(int mask)
    {
    	if (dp[mask] != -1) return dp[mask];
    	if (mask == 0) return 0;
    	int &ret = dp[mask];
    	ret = INF;
    	int x = 0;
    	while (!(mask & (1 << x))) x++;
    	for (int i = x + 1; i < 2 * K; i++)
    		if (mask & (1 << i)) ret = min(ret, solve(mask ^ (1 << x) ^ (1 << i)) + dis[x][p[i].sec]);
    	return ret;
    }
    
    int main()
    {
    	freopen("starlit.in", "r", stdin);
    	freopen("starlit.out", "w", stdout);
    	scanf("%d %d %d", &n, &K, &m);
    	for (int i = 1, x; i <= K; i++) scanf("%d", &x), a[x] = true;
    	for (int i = 1; i <= m; i++) scanf("%d", &b[i]);
    	for (int i = 0; i <= n; i++) if (a[i] != a[i + 1]) p[cnt] = pii(cnt, i), cnt++;
    	for (int i = 0; i < cnt; i++) bfs(p[i]);
    	memset(dp, -1, sizeof dp);
    	int ans = solve((1 << cnt) - 1);
    	assert(ans != INF);
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7652931.html
Copyright © 2011-2022 走看看