2018.11.3 PION模拟赛

期望:100    实际:100

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,s,num;
int a[MAXN];
long long ans;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int cmp(int x,int y){
    return x>y;
}
int main(){
    freopen("median.in","r",stdin);
    freopen("median.out","w",stdout);
    n=read();s=read();
    for(int i=1;i<=n;i++)    a[i]=read();
    sort(a+1,a+1+n,cmp);
    int mid=n/2;
    for(int i=1;i<=n;i++)
        if(a[i]>=s)    num++;
        else{
            if(num<=mid){
                ans+=(s-a[i]);num++;
            }    
            else if(num>mid)    break;
        }
    cout<<ans;
}
100

 期望:20~40    实际:0

/*
思路:感觉可以用卡特兰数搞一下。
应该可以推出递推式。 
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,p,k;
long long ans;
int vis[10010];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void dfs(int now,int num1,int num2){
    if(num1>n)    return ;
    if(num1+(2*n-now)+1<n)    return ;
    if(num2-num1>=k)    return ;
    if(now==2*n+1){
        if(num1==n){
            ans+=1;
            ans%=p;
        }
        return ;
    }
    vis[now]=1;dfs(now+1,num1+1,num2);vis[now]=0;
    dfs(now+1,num1,num2+1);
}
int main(){
    freopen("term.in","r",stdin);
    freopen("term.out","w",stdout);
    n=read();k=read();p=read();
    if(n<=15){
        dfs(1,0,0);
        printf("%d\n",ans);
    }
    else if(k==1){
        ans=1;
        for(int i=2*n;i>=n+2;i--){
            int j=2,num=i;
            while(j<=n){
                if(!vis[j]){
                    if(num%j==0){
                        num/=j;
                        vis[j]=1;
                    }
                }
                j++;
            }
            ans=ans*num;
        }
        for(int i=2;i<=n;i++)
            if(!vis[i])    ans/=i;
        cout<<ans%p;
    }
}
0

看出是卡特兰数了,但是对于非质数的除法取莫出现了问题

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,p,tot;
int prime[10000],num[100000];
int vis[10010],mn[100010],yes[100010];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void pre(){
    memset(yes,true,sizeof(yes));
    yes[1]=false;
    for(int i=2;i<=2*n;i++){
        if(yes[i])    prime[++tot]=i,mn[i]=tot;
        for(int j=1;i*prime[j]<=n;j++){
            yes[i*prime[j]]=false;
            if(i%prime[j]==0)    break;    
        }
    }
}
void insert(int x,int opt){
    while(x!=1){
        num[mn[x]]+=opt;
        x=x/prime[mn[x]];
    }
}
int fastpow(long long a,long long b){
    long long s=1;
    for(;b;b>>=1){
        if(b&1)    s=a*a%p;
        a=a*a%p;
    }
    return s;
}
int findans(){
    long long ans=1;
    for(int i=1;i<=tot;i++)
        if(num[i])
            ans=(1ll*ans*fastpow(prime[i],num[i]))%p;
    return ans;
}
int main(){
//    freopen("term.in","r",stdin);
    //freopen("term.out","w",stdout);
    n=read();k=read();p=read();
    pre();
    for(int i=n+1;i<=2*n;i++)    insert(i,1);
    for(int i=1;i<=n;i++)    insert(i,-1);
    long long ans1=findans();
    memset(num,0,sizeof(num));
    for(int i=n+k+1;i<=2*n;i++)    insert(i,1);
    for(int i=1;i<=n-k;i++)    insert(i,-1);
    long long  ans2=findans();
    cout<<(ans1-ans2+p)%p;
}
100

 

发现正反跑spfa有70分。

#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 500010
using namespace std;
map<int,bool>ma[MAXN];
int tim,top,sumcol;
int n,m,s,t,tot,tot1,tot2;
struct nond{ int id,dis; };
int low[MAXN],dfn[MAXN],col[MAXN];
int val[MAXN],val1[MAXN],di[MAXN],dis[MAXN];
int stack[MAXN],vis[MAXN],visstack[MAXN];
int to[MAXN],cap[MAXN],net[MAXN],head[MAXN];
int to1[MAXN],cap1[MAXN],net1[MAXN],head1[MAXN];
int to2[MAXN],cap2[MAXN],net2[MAXN],head2[MAXN];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void add(int u,int v,int w){
    to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
}
void add2(int u,int v,int w){
    to1[++tot1]=v;cap1[tot1]=w;net1[tot1]=head1[u];head1[u]=tot1;
}
void add3(int u,int v,int w){
    to2[++tot2]=v;cap2[tot2]=w;net2[tot2]=head2[u];head2[u]=tot2;
}
void tarjin(int now){
    low[now]=dfn[now]=++tim;
    stack[++top]=now;
    vis[now]=1;visstack[now]=1;
    for(int i=head[now];i;i=net[i])
        if(visstack[to[i]])
            low[now]=min(low[now],dfn[to[i]]);
        else if(!vis[to[i]]){
            tarjin(to[i]);
            low[now]=min(low[now],low[to[i]]);
        }
    if(dfn[now]==low[now]){
        sumcol++;
        col[now]=sumcol;
        while(stack[top]!=now){
            col[stack[top]]=sumcol;
            visstack[stack[top]]=0;
            top--;
        }
        visstack[now]=0;
        top--;
    }
}

void spfa(int S){
    queue<int>que;
    memset(vis,0,sizeof(vis));
    memset(di,0x7f,sizeof(di));
    vis[S]=1;di[S]=val1[S];
    que.push(S);
    while(!que.empty()){
        int now=que.front();
        que.pop();
        vis[now]=0;
        for(int i=head1[now];i;i=net1[i])
            if(di[to1[i]]>=(di[now]&cap1[i]&val1[to1[i]])){
                di[to1[i]]=(di[now]&cap1[i]&val1[to1[i]]);
                if(!vis[to1[i]]){
                    vis[to1[i]]=1;
                    que.push(to1[i]);
                }
            }
    }
}
void spfa1(int S){
    queue<int>que;
    memset(vis,0,sizeof(vis));
    memset(dis,0x7f,sizeof(di));
    vis[S]=1;dis[S]=val1[S];
    que.push(S);
    while(!que.empty()){
        int now=que.front();
        que.pop();
        vis[now]=0;
        for(int i=head2[now];i;i=net2[i])
            if(dis[to2[i]]>=(dis[now]&cap2[i]&val1[to2[i]])){
                dis[to2[i]]=(dis[now]&cap2[i]&val1[to2[i]]);
                if(!vis[to2[i]]){
                    vis[to2[i]]=1;
                    que.push(to2[i]);
                }
            }
    }
}
int main(){
    freopen("rabbit.in","r",stdin);
    freopen("rabbit.out","w",stdout);
    n=read();m=read();s=read();t=read();
    for(int i=1;i<=n;i++)    val[i]=read();
    for(int i=1;i<=m;i++){
        int u=read();
        int v=read();
        int w=read();
        add(u,v,w);
    }
    for(int i=1;i<=n;i++)
        if(!vis[i])    tarjin(i);
    for(int i=1;i<=n;i++)
        for(int j=head[i];j;j=net[j])
            if(col[i]!=col[to[j]])
                if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                    ma[col[i]][col[to[j]]]=1;
                    add2(col[i],col[to[j]],cap[j]);
                    add3(col[to[j]],col[i],cap[j]);
                }
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        if(!vis[col[i]])    val1[col[i]]=val[i],vis[col[i]]=1;
        else val1[col[i]]=(val1[col[i]]&val[i]);
    for(int i=1;i<=n;i++)
        for(int j=head[i];j;j=net[j])
            if(col[i]==col[to[j]])
                val1[col[i]]=(val1[col[i]]&cap[j]);
    spfa(col[s]);
    spfa1(col[t]);
    if(di[col[t]]==0x7f7f7f7f){ puts("-1");return 0; }
    else{ printf("%d\n",min(di[col[t]],dis[col[s]]));return 0; }
}
70tarjin缩点+正反跑spfa
/*
————该题目主要考察tarjan缩点,拓扑排序和贪心
40pts:
直接爆搜,看每条边走不走,复杂度 ,此部分分贪心将所有权值&起来是有分的(给对题目做了一定分析的盆友的彩蛋)
60pts:
对于M = N - 1的点,其实他并不是树QWQ,因为题目中明确说了不保证联通,所以这个部分分是个假的。但是为了多给大家送点分,此部分数据采用随机生成,不论是用不正确的spfa还是dijkstra都能够跑过去,是不是很良心。
80pts:
考虑每个联通分量中,能走的肯定要尽量去走,然后我们缩点求出连通分量的贡献,转换成DAG上的问题,然后发现DAG上不能够简单地按照拓扑序取min做dp转移,但是我们可以对DAG上每一个位置开一个64的数字记录到这个节点各个数字是否可行,然后拓扑序转移,复杂度64(N + M) 还是能跑过去的
100pts:
既然每个二进制位上的数字互不干扰,我们就拆分二进制做。
考虑从高位向低位枚举二进制位,我们肯定是希望高位上能够为0,那么我们考虑在整个DAG中的那些路径是能够使这一位为0的,显然,在所有从s到t的道路中,若存在某个点或者边,那么他所有的后继路径和前驱路径都是可行的,那么我们可以正反拓扑两次找到所有可行的点边集合作为当前答案。
然后考虑下一位,下一位中因为要保证上一位是0,所以能够走的点和边肯定是上次得到的点边集合里的,我们在这个得到的集合中在尽行同样的拓扑看看当前位是否可行,如果可行的话就用新得到的点边集合去更新原图的点边集合。
如此做三十次考虑所有的为就能得到答案了。
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#include<ctime>
#include<cmath>
#include<set>
#include<map>
#define ll long long
#define M 700010
struct Edge {
    int vi, vj, v;
} edge[M];
struct Note {
    int vj, v, id;
} be;
using namespace std;
int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
    return nm * f;
}
vector<int>to[M];
vector<Note> to1[M], to2[M];
int belong[M], st[M], dfn[M], low[M], dft, n, m, s, t, note[M], noww[M], tp, tot, sz[M], ans = 2147483647, rudu1[M], rudu2[M];
bool vis[M];
void tarjan(int now) {
    vis[now] = true;
    st[++tp] = now;
    dfn[now] = low[now] = ++dft;
    for(int i = 0; i < to[now].size(); i++) {
        int vj = to[now][i];
        if(!dfn[vj]) {
            tarjan(vj);
            low[now] = min(low[now], low[vj]);
        } else if(vis[vj]) low[now] = min(low[now], dfn[vj]);
    }
    if(dfn[now] == low[now]) {
        tot++;
        while(st[tp] != now) {
            int x = st[tp];
            vis[x] = false;
            noww[tot] &= note[x];
            belong[x] = tot;
            tp--;
        }
        int x = st[tp];
        vis[x] = false;
        noww[tot] &= note[x];
        belong[x] = tot;
        tp--;
    }
}
bool can[M], tmp1[M], tmp2[M];
int note1[M], note2[M], tp1, tp2;

void tuopu() {
    queue<int>q;
    q.push(belong[t]);
    while(!q.empty()) {
        int op = q.front();
        q.pop();
        for(int i = 0; i < to2[op].size(); i++) {
            int vj = to2[op][i].vj;
            rudu2[vj]++;
            if(!vis[vj]) q.push(vj), vis[vj] = true;
        }
    }
    while(!q.empty()) q.pop();
    q.push(belong[s]);
    while(!q.empty()) {
        int op = q.front();
        note1[++tp1] = op;
        q.pop();
        for(int i = 0; i < to1[op].size(); i++) {
            int vj = to1[op][i].vj;
            rudu1[vj]--;
            if(rudu1[vj] == 0) q.push(vj);
        }
    }
    q.push(belong[t]);
    while(!q.empty()) {
        int op = q.front();
        q.pop();
        note2[++tp2] = op;
        for(int i = 0; i < to2[op].size(); i++) {
            int vj = to2[op][i].vj;
            rudu2[vj]--;
            if(rudu2[vj] == 0) q.push(vj);
        }
    }
}

void work(int x) {
    for(int i = 1; i <= tot; i++) tmp1[i] = tmp2[i] = false;
    if((noww[belong[s]] & x) == 0) tmp1[belong[s]] = true;
    for(int i = 1; i <= tp1; i++) {
        int op = note1[i];
        for(int j = 0; j < to1[op].size(); j++) {
            be = to1[op][j];
            if((tmp1[op] == true) || (can[be.id] && ((be.v & x) == 0))) {
                tmp1[be.vj] = true;
                tmp1[be.id] = true;
            } else if((noww[be.vj] & x) == 0 && (can[be.vj])) tmp1[be.vj] = true;
        }
    }
    if((noww[belong[t]] &x) == 0) tmp2[belong[t]] = true;
    for(int i = 1; i <= tp2; i++) {
        int op = note2[i];
        for(int j = 0; j < to2[op].size(); j++) {
            be = to2[op][j];
            if((tmp2[op] == true) || (can[be.id] && ((be.v & x) == 0))) {
                tmp2[be.vj] = true;
                tmp2[be.id] = true;
            } else if((noww[be.vj] & x) == 0 && (can[be.vj])) tmp2[be.vj] = true;
        }
    }
    for(int i = 1; i <= tot; i++) tmp1[i] = (tmp1[i] | tmp2[i]);
    if(tmp1[belong[s]] && tmp1[belong[t]]) ans -= x;
    else return;
    for(int i = 1; i <= tot; i++) can[i] = (can[i] & tmp1[i]);
}
int main() {
    freopen("rabbit.in", "r", stdin);
    freopen("rabbit.out", "w", stdout);
    cin >> n >> m >> s >> t;
    for(int i = 1; i <= n; i++) note[i] = read(), noww[i] = 2147483647;
    for(int i = 1; i <= m; i++) {
        int vi = read(), vj = read(), v = read();
        edge[i].vi = vi, edge[i].vj = vj, edge[i].v = v;
        to[vi].push_back(vj);
    }
    tarjan(s);
    if(!dfn[t]) {
        puts("-1");
        return 0;
    }
    for(int i = 1; i <= m; i++) {
        int vi = edge[i].vi, vj = edge[i].vj, v = edge[i].v;
        vi = belong[vi], vj = belong[vj];
        if(vi == 0 || vj == 0) continue;
        if(vi == vj) noww[vi] &= v;
        else {
            be.id = ++tot;
            be.vj = vj;
            be.v = v;
            to1[vi].push_back(be);
            rudu1[vj]++;
            be.vj = vi;
            to2[vj].push_back(be);
        }
    }
    if(belong[s] == belong[t]) {
        cout << noww[belong[s]] << "\n";
        return 0;
    }
    tuopu();
    for(int i = 1; i <= tot; i++) can[i] = true;
    for(int i = 30; i >= 0; i--) work(1 << i);
    cout << ans << "\n";
    return 0;
}
std

 

posted @ 2018-11-05 15:03  一蓑烟雨任生平  阅读(174)  评论(0编辑  收藏  举报