hdu2018多校七

Age of Moyu

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1029    Accepted Submission(s): 286

Problem Description

Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting of N ports and M shipping lines. The ports are numbered 1 to N. Each line is occupied by a Weitian. Each Weitian has an identification number.

The i-th (1≤i≤M) line connects port Ai and Bi (Ai≠Bi) bidirectionally, and occupied by Ci Weitian (At most one line between two ports).

When Mr.Quin only uses lines that are occupied by the same Weitian, the cost is 1 XiangXiangJi. Whenever Mr.Quin changes to a line that is occupied by a different Weitian from the current line, Mr.Quin is charged an additional cost of 1 XiangXiangJi. In a case where Mr.Quin changed from some Weitian A's line to another Weitian's line changes to Weitian A's line again, the additional cost is incurred again.

Mr.Quin is now at port 1 and wants to travel to port N where live many fishes. Find the minimum required XiangXiangJi (If Mr.Quin can’t travel to port N, print −1 instead)

Input

There might be multiple test cases, no more than 20. You need to read till the end of input.

For each test case,In the first line, two integers N (2≤N≤100000) and M (0≤M≤200000), representing the number of ports and shipping lines in the city.

In the following m lines, each contain three integers, the first and second representing two ends Ai and Bi of a shipping line (1≤Ai,Bi≤N) and the third representing the identification number Ci (1≤Ci≤1000000) of Weitian who occupies this shipping line.

Output

For each test case output the minimum required cost. If Mr.Quin can’t travel to port N, output −1 instead.

Sample Input

3 3

1 2 1

1 3 2

2 3 1

2 0

3 2

1 2 1

2 3 2

Sample Output

1

-1

2

题意:给出一张无向图,给边染色,在通过相同颜色的边旅行花费永远是1,每次通过的边的颜色变一下,花费就增加一下。

思路:这里我采用了dijkstra堆优化加上dfs的方法,bfs+dfs应该也可以,这题数据水,很多都过了。

#include <bits/stdc++.h>
#define maxn 200005
using namespace std;
struct edge
{
    int u;
    int v;
    int w;
    int next;
}edge[2*maxn];
int head[maxn];
vector<int>mp[maxn];
int cnt=0;
int n;
void addedge(int u,int v,int w)
{
     edge[cnt].u=u;
     edge[cnt].v=v;
     edge[cnt].w=w;
     edge[cnt].next=head[u];
     head[u]=cnt++;
}
int dist[maxn];
priority_queue < pair<int,int>,vector < pair<int,int> >,greater<pair<int,int> > >q;
void dfs(int x,int val,int col)
{
    for(int i = head[x];i!=-1;i=edge[i].next)
    {
        if(edge[i].w==col&&dist[edge[i].v]>val)
        {
            dist[edge[i].v]=val;
            q.push(make_pair(dist[edge[i].v],edge[i].v));
            mp[edge[i].v].clear();
            mp[edge[i].v].push_back(edge[i].w);
            dfs(edge[i].v,val,col);
        }
        else if(edge[i].w==col&&dist[edge[i].v]==val)
        {
            mp[edge[i].v].push_back(edge[i].w);
        }
    }
}
void dijkstra(int s,int t)
{
    int i,now;
    for(i=1;i<=n;i++)
    {
        dist[i]=0x7fffffff;
    }
    dist[s]=0;
    while(!q.empty())q.pop();
    q.push(make_pair(0,s));
    while(!q.empty())
    {
        
        now=q.top().second;
        if(q.top().first>dist[now])
        {
            q.pop();
            continue;
        }
        q.pop();
        for(i=head[now];i!=-1;i=edge[i].next)
        {
            int flag = 1;
            for(int j =0;j<mp[now].size();j++)
            {
                if(mp[now][j]==edge[i].w)
                {
                    flag = 0;
                    break;
                }
            }
            int dd = dist[now] + flag;
            if(dd<dist[edge[i].v])
            {
                dist[edge[i].v]=dd;
                q.push(make_pair(dist[edge[i].v],edge[i].v));
                mp[edge[i].v].clear();
                mp[edge[i].v].push_back(edge[i].w);
                dfs(edge[i].v,dd,edge[i].w);
            }
            else if(dd==dist[edge[i].v])
            {
                mp[edge[i].v].push_back(edge[i].w);
                dfs(edge[i].v,dd,edge[i].w);
            }
        }
    }
}
int main()
{
    int m,t;
    while(~scanf("%d%d",&n,&m))
    {
        cnt = 0;
        for(int i = 0;i<=n;i++)mp[i].clear();
        memset(head,-1,sizeof(head));
        for(int i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dijkstra(1,n);
        if(dist[n]==0x7fffffff)printf("-1\n");
        else printf("%d\n",dist[n]);
    }
        return 0;
}

Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 446    Accepted Submission(s): 141

Problem Description

Let us define a sequence as below

⎧⎩⎨⎪⎪⎪⎪⎪⎪F1F2Fn===ABC⋅Fn−2+D⋅Fn−1+⌊Pn⌋
  Your job is simple, for each task, you should output Fn module 109+7

Input

The first line has only one integer T, indicates the number of tasks.

Then, for the next T lines, each line consists of 6 integers, A , B, C, D, P, n.

1≤T≤200≤A,B,C,D≤1091≤P,n≤109

Sample Input

2

3 3 2 1 3 5

3 2 2 2 1 4

Sample Output

36

24

题意:给出一个递推公式,求出第n个的值。

思路:n比较大应该是需要矩阵快速幂,p/n又一直在变,所以采用分块矩阵快速幂,前一部分可以O(n)算出来,后面分块矩阵快速幂。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1e6+10;
typedef vector<ll> vec;
typedef vector<vec> mat;
typedef long long ll;
ll f[maxn];
const ll M=1e9+7;       //模数 
//计算A*B 
mat mul(mat &A,mat &B)
{
	mat C(A.size(),vec(B[0].size()));
	for(int i=0;i<A.size();i++)
	{
		for(int k=0;k<B.size();k++)
		{
			for(int j=0;j<B[0].size();j++)
			{
				C[i][j]=(C[i][j]+(ll)A[i][k]*B[k][j])%M;
			}
		}
	}
	return C;
}
//计算A^n 
mat pow(mat A,ll n)
{
	mat B(A.size(),vec(A.size()));
	for(int i=0;i<A.size();i++)
	{
		B[i][i]=1;
	}
	while(n>0)
	{
		if(n&1)B=mul(B,A);
		A=mul(A,A);
		n>>=1;
	}
	return B;
}

int main()
{
    int t;
    ll a,b,c,d,p,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&p,&n);
        f[1] = a;
        f[2] = b;
        for(int i = 3;i<maxn;i++)
        {
            f[i] = ((c*f[i-2])%mod +(d*f[i-1])%mod + p/i)%mod;
        //    cout<<" i ="<<i<<"  f = "<<f[i]<<endl;
            if(i==n)break;
        }
        if(n<maxn)
        {
            printf("%lld\n",f[n]);
            continue;
        }
        mat A(3,vec(3));
        mat tmp(3,vec(3));
        A[0][0] = d;
        A[0][1] = c;
        A[0][2] = 1;
        A[1][0] = 1;
        A[1][1] = 0;
        A[1][2] = 0;
        A[2][0] = 0;
        A[2][1] = 0;
        A[2][2] = 1;
        mat B(3,vec(1));
        B[0][0] = f[maxn - 1];
        B[1][0] = f[maxn - 2];
    //    cout<<f[2]<<" "<<f[3]<<endl;
        B[2][0] = p/maxn;
        for(int i = maxn;i<n+1;)
        {
        //    cout<<" i = "<<i<<endl;
            if(p/i==0)
            {
                int len =  n+1 - i;
                tmp = pow(A,len);
                B = mul(tmp,B);
                break;
            }
            int pl;
            if(p/i==1)
            {
                pl = p+1;
            }
            else{
                pl = (ll)p/(p/i)+1;
            }
            if(pl>n+1)pl = n+1;
            int len = pl - i;
        //    cout<<"pl = "<<pl<<endl;
        //    cout<<"len = "<<len<<endl;
            tmp = pow(A,len);
            B = mul(tmp,B);
            B[2][0] = p/pl;
        //    cout<<" i = "<<pl<<" f = "<<B[0][0]<<endl;
            i = pl;
        }
        printf("%lld\n",B[0][0]);
    }
}

Swordsman

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 594    Accepted Submission(s): 162

Problem Description

Lawson is a magic swordsman with k kinds of magic attributes v1,v2,v3,…,vk. Now Lawson is faced with n monsters and the i-th monster also has k kinds of defensive attributes ai,1,ai,2,ai,3,…,ai,k. If v1≥ai,1 and v2≥ai,2 and v3≥ai,3 and … and vk≥ai,k, Lawson can kill the i-th monster (each monster can be killed for at most one time) and get EXP from the battle, which means vj will increase bi,j for j=1,2,3,…,k.
Now we want to know how many monsters Lawson can kill at most and how much Lawson's magic attributes can be maximized.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line has two integers n and k (1≤n≤105,1≤k≤5).
The second line has k non-negative integers (initial magic attributes) v1,v2,v3,…,vk.
For the next n lines, the i-th line contains 2k non-negative integers ai,1,ai,2,ai,3,…,ai,k,bi,1,bi,2,bi,3,…,bi,k.
It's guaranteed that all input integers are no more than 109 and vj+∑i=1nbi,j≤109 for j=1,2,3,…,k.

It is guaranteed that the sum of all n ≤5×105.
The input data is very large so fast IO (like `fread`) is recommended.

Output

For each test case:
The first line has one integer which means the maximum number of monsters that can be killed by Lawson.
The second line has k integers v′1,v′2,v′3,…,v′k and the i-th integer means maximum of the i-th magic attibute.

Sample Input

1

4 3

7 1 1

5 5 2 6 3 1

24 1 1 1 2 1

0 4 1 5 1 1

6 0 1 5 3 1

Sample Output

3

23 8 4

Hint

For the sample, initial V = [7, 1, 1] ① kill monster #4 (6, 0, 1), V + [5, 3, 1] = [12, 4, 2] ② kill monster #3 (0, 4, 1), V + [5, 1, 1] = [17, 5, 3] ③ kill monster #1 (5, 5, 2), V + [6, 3, 1] = [23, 8, 4] After three battles, Lawson are still not able to kill monster #2 (24, 1, 1) because 23 < 24.

 题意:一个骑士取打怪兽,有v个技能,每个怪兽有v个防守值,必须所有技能都大于等于防守值才能打败他。打败之后每个技能能获得一些增加。求最终呢打败的怪兽数,以及每个技能大小。

思路:每个技能排个序,从前到后扫过去,见代码。fread重要。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
struct FastIO {
    static const int S = 1e7;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar() {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) exit(0);
        return buf[pos++];
    }
    inline int xuint() {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos++] = x;
    }
    inline void wint(ll x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
        wchar('\n');
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
struct node
{
    int a;
    int id;
}dat[5][maxn];
bool cmp(const node x,const node y)
{
    return x.a<y.a;
}
int b[maxn][5];
int num[maxn];
int v[5];
int tmp[5];
int pt[5];
int main()
{
    int t;
    t = io.xint();
    int n,k;
    while(t--)
    {
        n = io.xint();
        k = io.xint();
    //    scanf("%d%d",&n,&k);
        for(int i =0;i<k;i++)
        {
            v[i] = io.xint();
        //    scanf("%d",&v[i]);
        }
        for(int i =0;i<n;i++)
        {
            for(int j =0;j<k;j++)
            {
            //    scanf("%d",&dat[j][i].a);
                dat[j][i].a = io.xint();;
                dat[j][i].id = i;
            }
            for(int j = 0;j<k;j++)
            {
             //   scanf("%d",&b[i][j]);
                b[i][j] = io.xint();;
            }
        }
        memset(pt,0,sizeof(pt));
        for(int i = 0;i<k;i++)sort(dat[i], dat[i]+n ,cmp);
        memset(num,0,sizeof(num));
        int cnt = 0;
        while(true)
        {
            memset(tmp,0,sizeof(tmp));
            bool flag = false;
            for(int i = 0;i<k;i++)
            {
                while(true)
                {
                    if(dat[i][pt[i]].a>v[i]||pt[i]>=n)break;
                    num[dat[i][pt[i]].id]++;
                    if(num[dat[i][pt[i]].id]>=k)
                    {
                        cnt++;
                        flag = true;
                        for(int p = 0;p<k;p++)
                        {
                            v[p]+=b[dat[i][pt[i]].id][p];
                        }
                    }
                    pt[i]++;
                }
            }
            if(!flag)break;
        }
        printf("%d\n",cnt);
        for(int i = 0;i<k;i++)
        {
            printf("%d%c",v[i],i==k-1?'\n':' ');
        }
    }
    
}

GuGuFishtion

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 240    Accepted Submission(s): 84

Problem Description

Today XianYu is too busy with his homework, but the boring GuGu is still disturbing him!!!!!!
At the break time, an evil idea arises in XianYu's mind.
‘Come on, you xxxxxxx little guy.’
‘I will give you a function ϕ(x) which counts the positive integers up to x that are relatively prime to x.’
‘And now I give you a fishtion, which named GuGu Fishtion, in memory of a great guy named XianYu and a disturbing and pitiful guy GuGu who will be cooked without solving my problem in 5 hours.’
‘The given fishtion is defined as follow:

Gu(a,b)=ϕ(ab)/ϕ(a)ϕ(b)


And now you, the xxxxxxx little guy, have to solve the problem below given m,n,p.’

(∑a=1m∑b=1nGu(a,b))(modp)


So SMART and KINDHEARTED you are, so could you please help GuGu to solve this problem?
‘GU GU!’ GuGu thanks.

Input

Input contains an integer T indicating the number of cases, followed by T lines. Each line contains three integers m,n,p as described above.
1≤T≤3
1≤m,n≤1,000,000
max(m,n)<p≤1,000,000,007
And given p is a prime.

Output

Please output exactly T lines and each line contains only one integer representing the answer.

Sample Input

1

5 7 23

Sample Output

2

题意:求题中公式的值。

思路:根据欧拉函数性质设a为N的质因数,若(N % a == 0 && (N / a) % a == 0) 则有E(N)=E(N / a) * a;若(N % a == 0 && (N / a) % a != 0) 则有:E(N) = E(N / a) * (a - 1)。

我们可以把原式化成ϕ(a1^(p1+p2))*ϕ(a2^(p1+p2))*...*ϕ(an^(p1+p2))/(ϕ(a1^p1)*ϕ(a1^p2)*ϕ(a2^p1)*ϕ(a2^p2)*...*ϕ(an^p1)*ϕ(an^p2)))------>a1*a2*...*an/(ϕ(a1)*ϕ(a2)*...*ϕ(an))------>a1*a2*...*an/(ϕ(a1*a2*...*an))------>再用性质一些操作后----->gcd(a,b)/ϕ(gcd(a,b))

得到,等价于,采用莫比乌斯反演就出后一部分即可。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int euler[maxn];
ll p;
void Init()
{
     memset(euler,0,sizeof(euler));
     euler[1]=1;
     for(int i=2;i<maxn;i++)
       if(!euler[i])
       for(int j=i;j<maxn;j+=i)
       {
              if(!euler[j])
               euler[j]=j;
               euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出
         }
}

bool vis[maxn];
int prime[maxn],mu[maxn];
ll sum[maxn];
void init_mu(int n){      //预处理莫比乌斯数
	memset(vis,0,sizeof(vis));
	memset(prime,0,sizeof(prime));
	memset(mu,0,sizeof(mu));
	memset(sum,0,sizeof(sum));
    int cnt=0;
    mu[1]=1;
    for(int i=2;i<n;i++){
        if(!vis[i])      //素数没有出现过 
		{
            prime[cnt++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<cnt&&i*prime[j]<n;j++)
		{
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)  // i*prime[j]为第三类,即包含重复素数的乘积,置0 
			{
				mu[i*prime[j]]=0;
				break;
			}
            else                //前两类 
				mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<n;i++)sum[i]=sum[i-1]+mu[i];   //计算mu[]的前缀和 
}
ll cal(ll a,ll b)   //反演
{
	int j;
	ll ans=0;
	for(int i=1;i<=b;i=j+1)
	{
		j=min(a/(a/i),b/(b/i));      //数论分块原理 
		ans+=(sum[j]-sum[i-1])*((a/i)*(b/i))%p;  //取模防止爆炸
	}
	return ans;
}
ll inv[maxn];
int main()
{
    Init();
    init_mu(maxn);
    ll n,m;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&n,&m,&p);
        if(n<m)swap(n,m);
        inv[1]=1;  
        for (int i=2;i<=m;i++)  
            inv[i]=((p-p/i)*inv[p%i])%p; 
        ll ans = 0;
        for(int i = 1;i<=m;i++)
        {
            ans = (ans + ((i*inv[euler[i]])%p*cal(n/i,m/i))%p)%p;     
        }
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/81636998