2018hdu多校第七场

版权声明:欢迎大佬指正! https://blog.csdn.net/sinat_36215255/article/details/81663450

其实这场两个队友点醒了我,就是我和另一个队友的思考风格是,喜欢想出一个思路来,然后根据各种情况分分分分,ifelseifelse,把情况考虑完,但是昨天另一个队友我俩想h的时候,我枚举了一下情况,他说太麻烦,就不行,我当时有点无语,他非要再想一个全部的方法不用考虑分情况那种,结果事实证明,这样还是不错的。

如果当时我们矩阵那个题能够这样再多想想,可能会有更好的,更清晰更具有包含性的写法,就不用写那么长,也不好查bug。

H题Traffic Network in Numazu

树链剖分,思路是去掉一条边,然后枚举要不要过这个边的两个端点,然后取最小。

网上找的板子,跟队友找了很久很久的bug,就是不明白哪里错了。

后来发现居然是数组开小了????? 但是不明白到底哪里开小了,需要数组再开大一倍;

ps:xyk直接把题目输入的最后一条边当做环中的一条边去掉,然后就AC了,这分分钟hack掉啊,这数据真滴秀,秀的我,,,

代码如下:

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#define N 100000+100
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Mid(x,y) ((x+y)>>1)
#define ll __int64
struct Edge
{
    ll from, to, dis,nex;
    bool yes;
} edge[N<<1];
ll c[N];
struct note
{
    ll u,v;
    ll len;
    note() {}
    note(ll u,ll v,ll len):u(u),v(v),len(len) {}
} aa[N];
int found(ll x)
{
    if(c[x]==x) return x;
    else return c[x]=found(c[x]);
}
bool same(ll x,ll y)
{
    return found(x)==found(y);
}
void unit(ll x,ll y)
{
    x=found(x);
    y=found(y);
    if(x==y) return;
    c[x]=y;
}
ll head[N], edgenum;
ll huan;
ll dis[N];
void addedge(ll u, ll v, ll d)
{
    Edge E= {u,v,d,head[u],false};
    edge[edgenum] = E;
    head[u] = edgenum++;
}
ll son[N];
ll top[N];
ll fp[N];
ll p[N];
ll siz[N];
ll dep[N];
ll fa[N];
ll tree_id;
void dfs(ll u, ll father, ll deep)
{
    fa[u] = father;
    dep[u] = deep;
    siz[u] = 1;
    for(ll i = head[u]; ~i; i = edge[i].nex)
    {
        ll v = edge[i].to;
        if(v == father)continue;
        dfs(v, u, deep+1);
        siz[u] += siz[v];
        if(son[u] == -1 || siz[son[u]]<siz[v])son[u] = v;
        dis[v] = edge[i].dis;
        edge[i].yes = true;
    }
}
void getpos(ll u, ll toppos)
{
    p[u] = tree_id++;
    fp[p[u]] = u;
    top[u] = toppos;
    if(son[u] == -1)return;
    if(u==0)getpos(son[u],son[u]);
    else getpos(son[u], toppos);
    for(int i = head[u]; ~i; i = edge[i].nex)
    {
        int v = edge[i].to;
        if(v == fa[u] || v == son[u])continue;
        getpos(v,v);
    }
}
struct node
{
    ll l, r;
    ll sum;
} tree[N*8];
void updata_up(ll id)
{
    tree[id].sum = tree[L(id)].sum+tree[R(id)].sum;
}
void build(ll l, ll r, ll id)
{
    tree[id].l = l, tree[id].r = r;
    tree[id].sum = 0;
    if(l == r)return ;
    int mid = Mid(l,r);
    build(l,mid,L(id)), build(mid+1,r,R(id));
}
void updata(ll pos, ll val, ll id)
{
    if(tree[id].l == tree[id].r)
    {
        tree[id].sum = val;
        return;
    }
    ll mid = Mid(tree[id].l,tree[id].r);
    if(pos <= mid)updata(pos, val, L(id));
    else updata(pos, val, R(id));
    updata_up(id);
}
ll query(ll l, ll r, ll id)
{
    if(l <= tree[id].l && tree[id].r <= r)return tree[id].sum;
    ll mid = Mid(tree[id].l, tree[id].r);
    ll ans = 0;
    if(l <= mid)ans+=query(l,r,L(id));
    if(r >  mid)ans+=query(l,r,R(id));
    return ans;
}
ll Query(ll x,ll y)
{
    ll f1 = top[x], f2 = top[y];
    ll ans = 0;
    while(f1 != f2)
    {
        if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y);

        ans += query(p[f1],p[x],1);
        x = fa[f1];
        f1 = top[x];
    }
    if(dep[x] > dep[y])swap(x,y);
    return ans + query(p[x],p[y],1) - query(p[x],p[x],1);;
}
void change(ll pos, ll val)
{
    Edge &E = edge[pos<<1];
    if(E.yes == false) E = edge[pos<<1|1];
    E.dis = val;
    updata(p[E.to], val, 1);
}
ll n, m;
void init()
{
    memset(head, -1, sizeof(head)), edgenum = 0;
    memset(son, -1, sizeof(son));
    for(int i=0; i<=n; i++)
        c[i]=i;
    tree_id = 1;
}
int main()
{
    int TT;
    scanf("%d",&TT);
    while(TT--)
    {
        ll i, j, u, v, d;
        scanf("%I64d %I64d",&n,&m);
            init();
            for(i = 1; i <= n; i++)
            {
                scanf("%I64d %I64d %I64d",&u,&v,&d);
                if(!same(u,v))
                {
                    addedge(u,v,d);
                    addedge(v,u,d);
                    unit(u,v);
                }
                else huan=i;
                aa[i]=note(u,v,d);
            }
            dfs(1,1,0);
            getpos(1,1);
            build(1,n,1);
            updata(p[1],0,1);
            for(i = 2; i <= n; i++)    updata(p[i],dis[i],1);

            while(m--)
            {
                scanf("%I64d %I64d %I64d",&d,&u,&v);
                if(d == 0)
                {
                    if(u<huan)
                        change(u-1,v);
                    else if(u==huan) aa[huan].len=v;
                    else
                    {
                        u--;
                        change(u-1,v);
                    }
                }
                else
                {
                    ll z1=Query(aa[huan].u,v)+Query(u,aa[huan].v);
                    ll z2=Query(u,aa[huan].u)+Query(aa[huan].v,v);
                    ll zz=min(z1,z2)+aa[huan].len;
                    ll hh=Query(u,v);
                    printf("%I64d\n",min(zz,hh));
                }

            }

    }

    return 0;
}

E题 (当时不会)

Ehttps://vjudge.net/contest/246642#problem/E

扫描二维码关注公众号,回复: 3215216 查看本文章

思路:

根据欧拉函数性质,

如果a中有一质因子p且幂为a1, 如果在b中为a2

      则phi(ab) = (p-1)p^(a1+a2-1)  , phi(a) *phi(b) = (p-1)*P^(a1-1) * (p-1)*p^(a2-1) 

   所以 gu(a,b) = p/(p-1)

如果a1 = 0  贼gu(a,b) = 1 ,,         a2 = 0,gu(a,b) = 1;

综上,gu(a,b) = gcd(a,b)  /phi( gcd(a,b) );

dls那个容斥甚好,甚好

(n,m)中  i | x  的数目为 f(i) =  (n/x) *(m/x) ;

n那么(n,m)中i == x  的数目为 d[i] = f[i] - sum( g(num * d)| num>=2)  )

代码:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e6+5;
//ll gcd(ll a,ll b)
//{
//    return b?gcd(b,a%b):a;
//}
//// head

long long inv[maxn];
long long f[maxn];
long long euler[maxn];
void init()
{
    euler[1] = 1;
    for(int i=2;i<maxn;i++)
       euler[i]=i;
    for(int i=2; i<maxn; i+=2)
        euler[i]/=2;
     for(int i=3;i<maxn;i+=2)
        if(euler[i]==i)
           for(int j=i;j<maxn;j+=i)
              euler[j]=euler[j]/i*(i-1);
}

int main()
{
    init();
    int n,m,mod;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&mod);
        if (n>m) swap(n,m);
        inv[1]=1;
        for (int i=2; i<=n; i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        long long ans =0;
        for(int i=n; i>=1; i--)
        {
            f[i] = (long long)(n/i)*(m/i);
            for(int j = i+i; j<=n; j+=i) f[i] -=f[j];
            ans = (ans + f[i] %mod * i %mod * inv[euler[i]]% mod)%mod;
        }
        printf("%lld\n",ans);
    }
}

 J Sequence 矩阵快速幂,

思路是一样的,关于实现的话,,,

看了看标程,哎,想想队友那代码,瞬间觉得我们还有很长的路要走。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
const long long mod=1e9+7;
struct jz
{
	long long num[3][3];
	jz() { memset(num,0,sizeof(num)); }
	jz operator*(const jz &P)const
	{
		jz ans;
		for(int k=0;k<3;k++)
			for(int i=0;i<3;i++)
				for(int j=0;j<3;j++)
					ans.num[i][j]=(ans.num[i][j]+num[i][k]*P.num[k][j]%mod)%mod;
		return ans;
	}
}COE,ans,unit;
int T_T;
long long A,B,C,D,P,n;
jz pOw(jz X,long long m)
{
	jz ans;
	for(ans=unit;m;m>>=1,X=X*X)
		if(m&1)
			ans=ans*X;
	return ans;
}
void init(long long A,long long B,long long C,long long D,long long x)
{
	COE.num[0][0]=0;
	COE.num[0][1]=1;
	COE.num[0][2]=0;
	COE.num[1][0]=C;
	COE.num[1][1]=D;
	COE.num[1][2]=x; // this element need to be changed each step.
	COE.num[2][0]=0;
	COE.num[2][1]=0;
	COE.num[2][2]=1;
	return;
}
int main()
{
	for(int i=0;i<3;i++) unit.num[i][i]=1;
	scanf("%d",&T_T);
	while(T_T--)
	{
		scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&n);
		if(n==1) printf("%lld\n",A);
		else if(n<P)
		{
			ans.num[0][0]=A;
			ans.num[1][0]=B;
			ans.num[2][0]=1;
			for(long long i=3;i<=n;i=P/(P/i)+1)
			{
				init(A,B,C,D,P/i);
				if(n<=P/(P/i)) COE=pOw(COE,n-i+1);
				else COE=pOw(COE,P/(P/i)+1-i);
				ans=COE*ans;
			}
			printf("%lld\n",ans.num[1][0]);
		}
		else if(P<=n)
		{
			ans.num[0][0]=A;
			ans.num[1][0]=B;
			ans.num[2][0]=1;
			for(long long i=3;i<=P;i=P/(P/i)+1)
			{
				init(A,B,C,D,P/i);
				COE=pOw(COE,P/(P/i)+1-i);
				ans=COE*ans;
			}
			init(A,B,C,D,0);
			COE.num[1][2]=0;
			COE=pOw(COE,n-max(P,2LL));
			ans=COE*ans;
			printf("%lld\n",ans.num[1][0]);
		}
	}
	
	return 0;
}

K - Swordsman

要用到输入挂。》》》

有点秀,没来的及想这个题,dls的思路

(听人念叨银行家算法,哈哈哈)

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5+5;
namespace fastIO {
	#define BUF_SIZE 100000
	//fread -> read
	bool IOerror = 0;
	inline char nc() {
		static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
		if(p1 == pend) {
			p1 = buf;
			pend = buf + fread(buf, 1, BUF_SIZE, stdin);
			if(pend == p1) {
				IOerror = 1;
				return -1;
			}
		}
		return *p1++;
	}
	inline bool blank(char ch) {
		return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
	}
	inline void read(int &x) {
		char ch;
		while(blank(ch = nc()));
		if(IOerror) return;
		for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
	}
	#undef BUF_SIZE
};
using namespace fastIO;
struct node
{
    int x;
    int id;
    node(int xx=0,int idd=0)
    {
        x = xx;
        id = idd;
    }
    bool operator<(const node& s)const
    {
        return x<s.x;
    }
    bool operator==(const node &s)const
    {
        return x==s.x;
    }
};
vector<node> a[6];
int vis[maxn];
int pos[6];
int s[6];
queue<int> q;
int b[maxn][6];
int main()
{
   //freopen("1.in", "r", stdin);
  // freopen("s.txt", "w", stdout);
    int n,m,mod;
    int T;
    //cin>>T;
    read(T);
    while(T--)
    {
        int n,k;
        int ans = 0;
        while(q.size())
            q.pop();
        memset(pos,0,sizeof(pos));
        memset(vis,0,sizeof(vis));
      	//cin>>n>>k;
      	read(n); read(k);
        for(int i=0; i<=k; i++)
            a[i].clear();
        for(int i=0; i<k; i++)
          //cin>>s[i];
         read(s[i]);
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<k; j++)
            {
                int x;
               // cin>>x;
                read(x);
                a[j].push_back(node(x,i));
            }
            for(int j=0; j<k; j++)
              //cin>>b[i][j];
                 read(b[i][j]);
        }
        for(int i=0; i<k; i++)
        {
            sort(a[i].begin(),a[i].end());
            int t = upper_bound(a[i].begin(),a[i].end(),node(s[i])) - a[i].begin();
            for(int j=pos[i]; j<t; j++)
            {
                int t = a[i][j].id;
                vis[t]++;
                if(vis[t]>=k)
                {
                    q.push(t);
                    ans++;
                    vis[t] = -1e5;
                }
            }
            pos[i] = t;
        }
        while(1)
        {
            while(q.size())
            {
                int d =q.front();
                q.pop();
                for(int i=0; i<k; i++)
                    s[i] += b[d][i];
            }
            int ok = 0;
            if(ans == n)
                break;
            for(int i=0; i<k; i++)
            {
                int t = upper_bound(a[i].begin(),a[i].end(),node(s[i])) - a[i].begin();
                for(int j=pos[i]; j<t; j++)
                {
                    int t = a[i][j].id;
                    vis[t]++;
                    if(vis[t]>=k)
                    {
                        q.push(t);
                        ans++;
                        vis[t] = -1e5;
                    }
                }
                pos[i] = t;
            }
            if(q.empty())
                break;
        }
        printf("%d\n",ans);
        for(int i=0; i<k; i++)
        {
            if(i!=0)
                printf(" ");
            printf("%d",s[i]);
        }
        cout<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_36215255/article/details/81663450