German Collegiate Programming Contest 2015

题目链接

B. Bounty Hunter II

求有向图中的最小路径覆盖。最小路径覆盖等于顶点数减去最大匹配数,直接用匈牙利算法即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define eps 1e-8
#define maxn 2050
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

int n,m,k,ans;
int flag[maxn],linker[maxn];
vector<int>q[maxn];

bool dfs(int x)
{
    for(int i=q[x].size()-1;i>=0;i--)
    {
        int u=q[x][i];
        if(!flag[u])
        {
            flag[u]=1;
            if(linker[u]==-1||dfs(linker[u]))
            {
                linker[u]=x;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        q[i].clear();
    for(int i=0;i<n;i++)
    {
        scanf("%d",&m);
        for(int j=0;j<m;j++)
        {
            scanf("%d",&k);
            q[i].push_back(k+n);
        }
    }
    ans=0;
    memset(linker,-1,sizeof(linker));
    for(int i=0;i<n;i++)
    {
        memset(flag,0,sizeof(flag));
        if(dfs(i))ans++;
    }
    printf("%d\n",n-ans);
    return 0;
}

E. Change of Scenery

无向图中判断1-n的最短路是否只有一条。

只需要维护一个num[i]表示从1到i最短路的数目,然后在dijkstra之后看num[n]是否大于1。

#include<cstdio>
#include<stack>
#include<map>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 10050
#define maxm 2000050
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long ll;

int n,m,k,no,x,y;
int head[maxn],num[maxn];
bool flag[maxn];
ll dis[maxn],z,a;
struct node
{
    int from;
    int to;
    ll w;
    int nxt;
}e[maxm];
void add(int x,int y,ll z)
{
    e[no].from=x;
    e[no].to=y;
    e[no].w=z;
    e[no].nxt=head[x];
    head[x]=no++;
}

void dijkstra()
{
    memset(flag,0,sizeof(flag));
    for(int i=0;i<=n;i++)
        dis[i]=1ll*INF;
    memset(num,0,sizeof(flag));
    dis[1]=0,num[1]=1;
    for(int i=1;i<=n;i++)
    {
        int kk=-1;
        ll minn=INF;
        for(int i=1;i<=n;i++)
        {
            if(!flag[i]&&dis[i]<minn)
            {
                minn=dis[i];
                kk=i;
            }
        }
        flag[kk]=1;
        for(int i=head[kk];i!=-1;i=e[i].nxt)
        {
            int v=e[i].to;
            int u=e[i].from;
            if(!flag[v])
            {
                if(dis[v]>dis[u]+e[i].w)
                {
                    dis[v]=dis[u]+e[i].w;
                    num[v]=num[u];
                }
                else if(dis[v]==dis[u]+e[i].w)
                    num[v]++;
            }
        }
    }
}

int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=k;i++)scanf("%lld",&a);
    no=0;
    memset(head,-1,sizeof(head));
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    dijkstra();
    if(num[n]>1)printf("yes\n");
    else printf("no\n");
    return 0;
}

F. Divisions

求一个数的因子数目。

一个结论:将一个数进行质因数分解,写成n=a1^e1*a1^e2*...*ak^ek的形式,那么因子数目就是(1+e1)*(1+e2)*...*(1+ek)。

由于这个数很大,质因数分解需要使用大数因数分解的Pollard_Rho算法。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
#define maxn 100050
#define INF 0x3f3f3f3f
#define eps 1e-8
typedef long long ll;

ll n;
ll fac[maxn];
int num=0;

ll mul(ll a,ll b,ll mod)
{
    if(!a) return 0;
     return ((a&1)*b%mod + (mul(a>>1,b,mod)<<1)%mod)%mod;
}

ll quickPow(ll a,ll d,ll n)
{
    ll ret = 1;
     while(d){
         if(d&1) ret = mul(ret,a,n);
         d >>= 1;
         a = mul(a,a,n);
     }
     return ret;
}

bool check(ll a,ll d,ll n)
{
     if(n == a) return true;
     while(~d&1) d >>= 1;
     ll t = quickPow(a,d,n);
     while(d < n-1 && t != 1 && t != n-1){
         t = mul(t,t,n);
         d <<= 1;
     }
     return (d&1)||t == n-1;
}

bool isP(ll n)
{
     if(n == 2) return true;
     if(n < 2 || 0 == (n&1)) return false;
     static int p[10] = {2,3,5,7,11,61,24251};
     for(int i = 0; i < 7; ++i)
         if(!check(p[i],n-1,n)) return false;
     return true;
}

ll gcd(ll a,ll b)
{
    ll t;
    while(b)
    {
        t=a;
        a=b;
        b=t%b;
    }
    if(a>=0)return a;
    else return -a;
}

ll pollard_rho(ll x,ll c)
{
    ll i=1,k=2;
    srand(time(NULL));
    ll x0=rand()%(x-1)+1;
    ll y=x0;
    while(1)
    {
        i++;
        x0=(mul(x0,x0,x)+c)%x;
        ll d=gcd(y-x0,x);
        if(d!=1&&d!=x)return d;
        if(y==x0)return x;
        if(i==k)
        {
            y=x0;
            k+=k;
        }
    }
}

void findfac(ll n,int k)
{
    if(n==1)return;
    if(isP(n))
    {
        fac[num++]=n;
        return;
    }
    ll p=n;
    int c=k;
    while(p>=n)
        p=pollard_rho(p,c--);
    findfac(p,k);
    findfac(n/p,k);
}

int main()
{
    scanf("%lld",&n);
    findfac(n,107);
    ll ans=1;
    for(int i=0;i<num;i++)
    {
        int cnt=0;
        while(n%fac[i]==0)
            n/=fac[i],cnt++;
        ans*=(cnt+1);
    }
    printf("%lld\n",ans);
    return 0;
}

G. Extreme Sort

给一个数列,判断是不是按升序排过序的。

I. Milling Machines

直接模拟,在每个位置上取工件的最大长度,然后把捅完后剩下的长度和模具的长度比较即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
#define maxn 10050
#define INF 0x3f3f3f3f
#define eps 1e-8
typedef long long ll;

int w,s,x,y,u;
int numw[maxn][105];
int nums[maxn];

int main()
{
    scanf("%d%d",&w,&s);
    scanf("%d%d",&x,&y);
    for(int i=0;i<w;i++)
    {
        for(int j=0;j<x;j++)
            scanf("%d",&numw[i][j]);
    }
    memset(nums,-1,sizeof(nums));
    for(int i=0;i<s;i++)
    {
        for(int j=0;j<x;j++)
        {
            scanf("%d",&u);
            nums[j]=max(nums[j],u);
        }
    }
    for(int i=0;i<w;i++)
    {
        for(int j=0;j<x;j++)
        {
            printf("%d",min(numw[i][j],y-nums[j]));
            if(j<x-1)printf(" ");
            else printf("\n");
        }
    }
    return 0;
}

K. Upside Down Primes

将一个七段译码器显示出来的数翻转,判断翻转前后是否都为素数。

除掉不合法的状况以后,就用Miller_Rabin算法判断是否为素数。


#include<cstdio>
#include<cstring>
#include<set>
#include<vector>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define maxn 19
#define INF 0x3f3f3f3f
#define mod 1e9+7
#define eps 1e-8
typedef long long ll;
using namespace std;

char s[maxn];
int n;

ll mul(ll a,ll b,ll mod) {
    if(!a) return 0;
     return ((a&1)*b%mod + (mul(a>>1,b,mod)<<1)%mod)%mod;
}
ll quickPow(ll a,ll d,ll n){
    ll ret = 1;
     while(d){
         if(d&1) ret = mul(ret,a,n);
         d >>= 1;
         a = mul(a,a,n);
     }
     return ret;
 }
 bool check(ll a,ll d,ll n){
     if(n == a) return true;
     while(~d&1) d >>= 1;
     ll t = quickPow(a,d,n);
     while(d < n-1 && t != 1 && t != n-1){
         t = mul(t,t,n);
         d <<= 1;
     }
     return (d&1)||t == n-1;
 }
 bool isP(ll n){
     if(n == 2) return true;
     if(n < 2 || 0 == (n&1)) return false;
     static int p[10] = {2,3,5,7,11,61,24251};
     for(int i = 0; i < 7; ++i)
         if(!check(p[i],n-1,n)) return false;
     return true;
}

int main()
{
    scanf("%s",s);
    n=strlen(s);
    ll ans=0,t=1;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='3'||s[i]=='4'||s[i]=='7')
        {
            printf("no\n");
            return 0;
        }
        else if(s[i]=='6')ans+=(t*9);
        else if(s[i]=='9')ans+=(t*6);
        else if(s[i]=='0'||s[i]=='1'||s[i]=='2'||s[i]=='5'||s[i]=='8')
            ans+=(t*(s[i]-'0'));
        t*=10;
    }
    ll qnm=0;
    ll cnm=1;
    for(int i=n-1;i>=0;i--)
    {
        qnm+=((s[i]-'0')*cnm);
        cnm*=10;
    }
    if(isP(ans)&&isP(qnm))
        printf("yes\n");
    else
        printf("no\n");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/81068058