第二周周练

中国(北方)大学生程序射击训练赛(第二周)

官方题解 

A.Common Substrings

字符串hash进行比较。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
string s1,s2;
LL p[100005];
int main(){
    p[0]=1;
    for(int i=1;i<100003;i++){
        p[i]=(p[i-1]*26)%mod;
    }
    int t;
    cin>>t;
    while(t--){
        cin>>s1>>s2;
        int ans=0;
        LL sum1=0,sum2=0;
        int len1=s1.size();
        int len2=s2.size();
        int len=min(len1,len2);
        for(int i=0;i<len;i++){
            LL v2=i,v1=len1-i-1;
            sum1=( sum1+(LL)(s1[v1]-'a')*p[i] )%mod;
            sum2=( sum2*26+(LL)(s2[v2]-'a') )%mod;
            if(sum1==sum2) ans++;
        }
        cout<<ans<<endl;
    }

    return 0;
}
Psong

B.A Boring Game

贪心。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
double a[4005];
int n;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++)
            scanf("%lf",&a[i]);
        int cnt=0;
        double sum=0;
        for(int i=1;i<=2*n;i++){
            if(a[i]-(int)a[i]<0.000001)
                cnt++;
            else
                sum+=a[i]-(int)a[i];
        }
        sum-=max(0,n-cnt);
        cnt=min(n,cnt);
        double ans=fabs(sum);
        for(int i=1;i<=cnt;i++){
            ans=min(ans,fabs(sum-i));
        }
        printf("%.3lf
",ans);
    }

    return 0;
}
Psong

C.A Water Problem

偶数考虑 i-1 和 i/2,奇数考虑 i-1 和 (i+1)/2。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
LL ans[10000006];
int n,x,y;
int main(){
    while(cin>>n>>x>>y){
        ans[1]=x;
        for(int i=2;i<=n;i++){
            if(i%2==0) ans[i]=min(ans[i-1]+x,ans[i/2]+y);
            else ans[i]=min(ans[i-1]+x,ans[i/2+1]+x+y);
        }
        cout<<ans[n]<<endl;
    }

    return 0;
}
Psong

D.MTM

网络流。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int> P;
struct edge{
    int to,cap,cost,rev;
};
vector<edge> g[1000005];
int V,n,m;
int dis[1000005],vis[1000005];
int prevv[1000005],preve[1000005];
void addedge(int from,int to,int cap,int cost){
    g[from].push_back((edge){to,cap,cost,g[to].size()});
    g[to].push_back((edge){from,0,-cost,g[from].size()-1});
}
void SPFA(int s,int t){
    fill(dis,dis+V,inf);
    fill(vis,vis+V,0);
    dis[s]=0; vis[s]=1;
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        int v=q.front();
        q.pop();
        vis[v]=0;
        for(int i=0;i<g[v].size();i++){
            edge &e=g[v][i];
            if(e.cap>0&&dis[e.to]>dis[v]+e.cost){
                dis[e.to]=dis[v]+e.cost;
                prevv[e.to]=v;
                preve[e.to]=i;
                vis[e.to]=1;
                q.push(e.to);
            }
        }
    }
}
int min_cost_flow(int s,int t,int f){
    int res=0;
    while(f>0){
        SPFA(s,t);
        if(dis[t]==inf) return -1;
        int d=f;
        for(int v=t;v!=s;v=prevv[v]){
            d=min(d,g[prevv[v]][preve[v]].cap);
        }
        f-=d;
        res+=d*dis[t];
        for(int v=t;v!=s;v=prevv[v]){
            edge &e=g[prevv[v]][preve[v]];
            e.cap-=d;
            g[v][e.rev].cap+=d;
        }
    }
    return res;
}
int a[1005],b[1005];
int p,q;
void solve(int u){
    vector<int> v;
    for(int i=0;i<g[u].size();i++){
        if(g[u][i].cap)
            v.push_back(g[u][i].to);
    }
    sort(v.begin(),v.end());
    for(int i=0;i<v.size();i++){
        printf("%d",v[i]);
        if(i==v.size()-1) printf("
");
        else printf(" ");
    }
}
int main(){
    while(~scanf("%d%d%d",&n,&p,&q)){
        V=n+4;
        for(int i=0;i<V;i++)
            g[i].clear();
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        for(int i=1;i<=n;i++){
            addedge(0,i,1,0);
            addedge(i,n+1,1,-a[i]);
            addedge(i,n+2,1,-b[i]);
        }
        addedge(n+1,n+3,p,0);
        addedge(n+2,n+3,q,0);
        int ans=-min_cost_flow(0,n+3,p+q);
        printf("%d
",ans);
        solve(n+1);
        solve(n+2);
    }

    return 0;
}
Psong

E.shandawang

F.Problen of No Name

先把边排序,按顺序用并查集合并,注意两边的大小是否大于t。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=250005;
struct node{
    int from,to,val;
} g[4*N];
bool cmp(node x,node y){
    return x.val<y.val;
}
int cnt;
int f[N];
int sz[N];
int ans[N];
int n,m,t,V;
void addedge(int u,int v,int val){
    g[cnt++]=(node){u,v,val};
}
void init(){
    V=n*m; cnt=0;
    for(int i=1;i<=V;i++){
        f[i]=i;
        sz[i]=1;
        ans[i]=0;
    }
}
int getid(int x,int y){
    return (x-1)*m+y;
}
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
void merge(int x,int y,int val){
    int fx=find(x);
    int fy=find(y);
    if(fx==fy) return;
    if(sz[fx]<sz[fy]) swap(fx,fy);
    if(sz[fx]<t&&sz[fy]<t){
        ans[fy]=val;
        sz[fy]+=sz[fx];
        f[fx]=fy;
    }
    if(sz[fx]>=t&&sz[fy]<t){
        ans[fy]=val;
        sz[fy]=t;
    }
}
int a[505][505];
int fx[]={1,0};
int fy[]={0,1};
int main(){
    while(~scanf("%d%d%d",&n,&m,&t)){
        init();
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            for(int k=0;k<2;k++){
                int xx=i+fx[k];
                int yy=j+fy[k];
                if(xx>n||yy>m)
                    continue;
                addedge(getid(i,j),getid(xx,yy),
                        abs(a[xx][yy]-a[i][j]));
            }
        }
        sort(g,g+cnt,cmp);
        for(int i=0;i<cnt;i++){
            if(find(g[i].from)==find(g[i].to)) continue;
            merge(g[i].from,g[i].to,g[i].val);
        }
        long long sum=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            int xx; cin>>xx;
            if(xx==1)
                sum+=ans[find(getid(i,j))];
        }
        cout<<sum<<endl;
    }

    return 0;
}
Psong

G.Connected Components

素数筛,并查集合并有相同素因子的元素

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
int f[1000010];
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
void merge(int x,int y){
    int fx=find(x);
    int fy=find(y);
    f[fx]=fy;
}
vector<int> p;
int vis[1000010];
void init(){
    for(int i=2;i<=1000006;i++){
        if(!vis[i]){
            p.push_back(i);
            LL k=(LL)i*i;
            while(k<=1000006){
                vis[k]=1;
                k+=i;
            }
        }
    }
}
int n;
void solve(int x){
    vector<int> g;
    for(int i=0;p[i]*p[i]<=x;i++){
        if(x%p[i]==0){
            g.push_back(p[i]);
            vis[p[i]]=1;
            while(x%p[i]==0) x/=p[i];
        }
    }
    if(x>1) g.push_back(x),vis[x]=1;;
    for(int i=1;i<g.size();i++){
        merge(g[0],g[i]);
    }
}
int k[1000010];
int main(){
    init();
    int t;
    scanf("%d",&t);
    int T=t;
    while(t--){
        memset(vis,0,sizeof(vis));
        memset(k,0,sizeof(k));
        for(int i=1;i<=1000006;i++) f[i]=i;

        int ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int a;
            scanf("%d",&a);
            if(a==1){
                ans++;
                continue;
            }
            solve(a);
        }

        for(int i=0;i<p.size();i++){
            if(vis[p[i]]){
                if(!k[find(p[i])]){
                    k[find(p[i])]=1;
                    ans++;
                }
            }
        }
        printf("Case %d: %d
",T-t,ans);
    }

    return 0;
}
Psong
原文地址:https://www.cnblogs.com/N-Psong/p/6558237.html