2017 Multi-University Training Contest - Team 4

rank 75/739

1003 Counting Divisors

筛法求出l到r区间内各个数字质因子的个数,对于每个数,d(x) = ∏(1+k*pi),pi为质因子指数。

#include <bits/stdc++.h>
using namespace std;
const int maxn=1000005;
const long long mod=998244353;
int T,tot;
bool is_prime[maxn];
long long l,r,K,prime[maxn],num[maxn],temp[maxn];
vector<long long> G[maxn];
int sieve() {
    int p=0;
    memset(is_prime,0,sizeof is_prime);
    is_prime[0]=is_prime[1]=1;
    for (int i=2;i<maxn;++i) {
        if (!is_prime[i]) {
            prime[p++]=i;
            for (int j=2*i;j<maxn;j+=i)
                is_prime[j]=1;
        }
    }
    return p;
}
void print() {
    for (int i=0;i<=r-l;++i) {
        printf("%I64d: ",i+l);
        for (int j=0;j<(int)G[i].size();++j)
            printf("%I64d ",G[i][j]);
        putchar('\n');
    }
}
int main()
{
    tot=sieve();
    scanf("%d",&T);
    while (T--) {
        scanf("%I64d%I64d%I64d",&l,&r,&K);
        for (long long i=0;i<=r-l;++i)
            num[i]=i+l,temp[i]=1;
        for (int i=0;i<tot;++i) {
            long long p=prime[i];
            for (long long j=(l+p-1)/p*p;j<=r;j+=p) {
                long long &tj=num[j-l];
                long long cnt=0;
                while (tj%p==0) {
                    tj/=p;
                    ++cnt;
                }
                temp[j-l]=temp[j-l]*(K*cnt+1)%mod;
            }
        }
        for (int i=0;i<=r-l;++i)
            if (num[i]>1)
                temp[i]=(temp[i]*(K+1))%mod;
        long long res=0;
        for (int i=0;i<=r-l;++i)
            res=(res+temp[i])%mod;
        cout<<res<<endl;
    }
    return 0;
}
1003

1004 Dirt Ratio

二分答案[0,1]C,区间内种类个数M,区间长度N,那么有M/N <=  c 为 true。转化为M - C * N   <=  0。遍历N,线段树维护以i为结尾的答案,如果1,i区间最小值小于等于0 返回true。

#include <bits/stdc++.h>
const long long mod = 1e9+7;
const double ex = 1e-10;
#define inf 0x3f3f3f3f
using namespace std;
map <int ,int> M;
int a[60005];
const int maxn = 60005;
struct node
{
    double val;
    double addmark;
} ST[4*maxn+5];
double A[maxn];
int N;
//修改求和还是维护区间最小值
double operation(double a,double b)
{
    //return a+b;
    return min(a,b);
}
//修改求和还是维护区间最小值
void change(int pos,double addmark,int l)
{
    ST[pos].val +=addmark;
}
void build(int root,int ibegin,int iend)
{
    ST[root].addmark = 0;
    if (ibegin==iend)
        ST[root].val = A[ibegin];
    else
    {
        int mid = (ibegin+iend)/2;
        build(2*root,ibegin,mid);
        build(2*root+1,mid+1,iend);
        ST[root].val = operation(ST[root*2].val,ST[root*2+1].val);
    }
}
void push_down(int root,int l)
{
    if (ST[root].addmark == 0) return;
    double  addmark = ST[root].addmark;
    ST[root*2].addmark+=addmark;
    ST[root*2+1].addmark+=addmark;
    change(root*2,addmark,l-l/2);
    change(root*2+1,addmark,l/2);
    ST[root].addmark = 0;
}
double query(int root,int ibegin,int iend,int qbegin,int qend)
{
    if (ibegin > qend || iend < qbegin)
        return 1e233;//
    if (ibegin>=qbegin&&iend<=qend)
        return ST[root].val;
    push_down(root,iend-ibegin+1);
    int mid = (ibegin+iend)/2;
    return operation(query(root*2,ibegin,mid,qbegin,qend),query(root*2+1,mid+1,iend,qbegin,qend));
}
void updata(int root,int ibegin,int iend,int qbegin,int qend,double addmark)
{
    if (ibegin > qend || iend < qbegin)
        return ;//
    if (ibegin>=qbegin&&iend<=qend)
        {
            ST[root].addmark+=addmark;
            change(root,addmark,iend-ibegin+1);
            return;
        }
    push_down(root,iend-ibegin+1);
    int mid = (ibegin+iend)/2;
    updata(root*2,ibegin,mid,qbegin,qend,addmark);
    updata(root*2+1,mid+1,iend,qbegin,qend,addmark);
    ST[root].val = operation(ST[root*2].val,ST[root*2+1].val);
}
int last[60005];
int t[60005];
bool check(double ans)
{
    for (int i = 1; i<=N; i++)
        A[i] = 0;
    build(1,1,N);
    for (int i = 1;i<=N; i++)
    {
        updata(1,1,N,last[i]+1,i,1.0);
        updata(1,1,N,1,i,-ans);
        if (query(1,1,N,1,i) < 0) return true;
    }
    return false;
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {

        scanf("%d",&N);
        for (int i = 1;i<=N;i++)
            t[i] = last[i] = 0;
        for (int i = 1;i<=N;i++)
        {
            scanf("%d",&a[i]);
            if (t[a[i]] == 0)
            {
                last[i] = 0;
            }
            else
            {
                last[i] = t[a[i]];
            }
            t[a[i]] = i;
        }
        int cnt = 0;
        double l = 0;
        double r = 1+ex;
        while (cnt++<=15)
        {
            double mid = (l+r)/2;
            if (check(mid))
                r = mid;
            else l = mid;
        }
        printf("%.10f\n",l);
    }
    return 0;
1004

1005 Lazy Running

取左右最小值W,转化为最短路,求%2*W的最短路。可以知道能够通过所求最短路和 重复来回走T次W来构造所有可能。

#include <bits/stdc++.h>
const long long mod = 1e9+7;
const double ex = 1e-10;
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
long long dis[6][60002];
int inq[6][60002];
long long a[6][6];
typedef pair<int,long long> pii;
long long W;
void spfa()
{
    memset(dis,inf,sizeof(dis));
    memset(inq,0,sizeof(inq));
    queue <pii> Q;
    Q.push(make_pair(1,0));
    dis[1][0] = 0;
    inq[1][0] = 1;
    while (!Q.empty()){
        int u = Q.front().first;
        long long  k = Q.front().second;

        if (dis[(u+1)%4][( k + a[u][ (u+1) % 4 ] ) % (2*W)]>dis[u][k] + (long long) a[u][ (u+1) % 4 ]){
            dis[(u+1)%4][( k + a[u][ (u+1) % 4 ] ) % (2*W)] = dis[u][k] + (long long)a[u][ (u+1) % 4 ];
            if (!inq[(u+1)%4][( k + a[u][ (u+1) % 4 ] ) % (2*W)]){
                Q.push(make_pair((u+1)%4,( k + a[u][ (u+1) % 4 ] ) % (2*W)));
                inq[(u+1)%4][( k + a[u][ (u+1) % 4 ] ) % (2*W)] = 1;
            }
        }
        if (dis[(u+3)%4][( k + a[u][ (u+3) % 4 ] ) % (2*W)]>dis[u][k] + (long long) a[u][ (u+3) % 4 ]){
            dis[(u+3)%4][( k + a[u][ (u+3) % 4 ] ) % (2*W)] = dis[u][k] + (long long)a[u][ (u+3) % 4 ];
            if (!inq[(u+3)%4][( k + a[u][ (u+3) % 4 ] ) % (2*W)]){
                Q.push(make_pair((u+3)%4,( k + a[u][ (u+3) % 4 ] ) % (2*W)));
                inq[(u+3)%4][( k + a[u][ (u+3) % 4 ] ) % (2*W)] = 1;
            }
        }
        Q.pop();
        inq[u][k] = 0;
    }
}
int main()
{
    int N;
    cin >> N;
    while (N--){
        long long K;
        cin >> K;
        for (int i = 0; i<=3; i++){
            long long  t;
            cin >> t;
            a[i][(i+1)%4] = t;
            a[(i+1)%4][i] = t;
        }
        W = min(a[1][2],a[0][1]);
        spfa();
        long long ans = inf;
        for (int i = 0 ; i<2*W ; i++){
            if (dis[1][i]>=K) ans = min(ans,dis[1][i]);
            else ans = min (ans,dis[1][i] + 2*W *((K-dis[1][i] + 2*W-1)/(2*W)) );
        }
        cout << ans <<endl;
    }
    return 0;
}
1005

1007 Matching In Multiplication【补】

一个特殊的二分图,找到图上的环,对于环上的点分为两种选择分为ai,bi;找到图上的链,对于这部分链,选择唯一为cj。所有完美匹配的乘积的和显然就是(ai+bi)cj。

#include <bits/stdc++.h>
using namespace std;
const int maxn=300015;
const long long mod=998244353;
typedef pair<int,long long> pil;
int deg[maxn],T,n,vis[maxn<<1],tot,head[maxn<<1],ok,pb,used[maxn<<1];
long long temp[maxn][2],res;
vector<long long> cir;
queue <int> Q;
struct ee {
    int to,next;
    long long w;
    bool flag;
} edge[maxn<<2];
void addedge(int u,int v,long long w) {
    edge[tot].w=w;
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].flag=0;
    head[u]=tot++;
    edge[tot].w=w;
    edge[tot].to=u;
    edge[tot].next=head[v];
    edge[tot].flag=0;
    head[v]=tot++;
};
void dfs(int u,int fa) {
    if (used[u]) return;
    if (vis[u]&&!used[u]) {
        ok=1;
        pb=u;
        return;
    }
    vis[u]=1;
    for (int i=head[u];~i;i=edge[i].next) {
        if (edge[i].flag)
            continue;
        if (edge[i].to == fa) continue;
        dfs(edge[i].to,u);
        if (ok) {
            edge[i].flag=true;
            edge[i^1].flag=true;
            cir.push_back(edge[i].w);
            used[u]=1;
            if (pb==u)
                ok=0;
            return;
        }
    }
}
void dfs2(int u,int col) {
    vis[u]=1;
    for (int i=head[u];~i;i=edge[i].next) {
        if (edge[i].flag)
            continue;
        if (vis[edge[i].to])
            continue;
        if (!col){
            res=res*edge[i].w%mod;
            dfs2(edge[i].to,!col);
        }
        else{
            deg[edge[i].to-n]--;
            if (deg[edge[i].to-n] == 1) dfs2(edge[i].to,!col);
        }

    }
}
int main()
{
    scanf("%d",&T);
    while (T--) {
        scanf("%d",&n);
        tot=0;
        memset(vis,0,(2*n+2)*sizeof vis[0]);
        memset(head,-1,(2*n+2)*sizeof head[0]);
        memset(deg,0,(n+1)*sizeof deg[0]);
        memset(used,0,(2*n+2)*sizeof used[0]);

        for (int i=1;i<=n;++i) {
            int v1,v2;
            long long w1,w2;
            scanf("%d%I64d%d%I64d",&v1,&w1,&v2,&w2);
            addedge(i,v1+n,w1);
            addedge(i,v2+n,w2);
            ++deg[v1];
            ++deg[v2];
        }
        for (int i=0;i<=n;++i)
            temp[i][0]=temp[i][1]=1;
        int cnt=0;
        for (int i=1;i<=n;++i)
            if (!vis[i]) {
                ok=0;
                cir.clear();
                dfs(i,-1);
                if (cir.size()==0) continue;
                ++cnt;
                for (int j=0;j<(int)cir.size();++j)
                    temp[cnt][j&1]=temp[cnt][j&1]*cir[j]%mod;
            }
        res=1;
        for (int i=1;i<=cnt;++i)
            res=res*((temp[i][0]+temp[i][1])%mod)%mod;
        memset(vis,0,sizeof vis);
        for (int i=n+1;i<=(n<<1);++i)
            if (deg[i-n]==1)
                dfs2(i,0);
        cout<<res<<endl;
    }
    return 0;
}
1007

1009 Questionnaire

m = 2 的时候显然模数只有0或1,取多的那个。

#include <bits/stdc++.h>
using namespace std;
int T,cnta,cntb,t,n,res;
int main()
{
    scanf("%d",&T);
    while (T--) {
        cnta=cntb=0;
        scanf("%d",&n);
        for (int i=1;i<=n;++i) {
            scanf("%d",&t);
            if (t&1)
                ++cnta;
            else
                ++cntb;
        }
        if (cnta>cntb)
            res=1;
        else
            res=0;
        printf("2 %d\n",res);
    }
    return 0;
}
1009

1011 Time To Get Up

模拟

#include <bits/stdc++.h>
const long long mod = 1e9+7;
const double eX = 1e-10;
#define inf 0X3f3f3f3f
using namespace std;
string s[10];
string ans[10];
int get(int u)
{
    if (s[2][u+2] == 'X') return 10;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='X'&&s[2][u]=='X'&&s[2][u+3]=='X'&&s[5][u]=='X'&&s[5][u+3]=='X'&&s[7][u+2]=='X') return 8;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='.'&&s[2][u]=='X'&&s[2][u+3]=='X'&&s[5][u]=='X'&&s[5][u+3]=='X'&&s[7][u+2]=='X') return 0;
    else if (s[1][u+2]=='.'&&s[4][u+2]=='.'&&s[2][u]=='.'&&s[2][u+3]=='X'&&s[5][u]=='.'&&s[5][u+3]=='X'&&s[7][u+2]=='.') return 1;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='X'&&s[2][u]=='.'&&s[2][u+3]=='X'&&s[5][u]=='X'&&s[5][u+3]=='.'&&s[7][u+2]=='X') return 2;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='X'&&s[2][u]=='.'&&s[2][u+3]=='X'&&s[5][u]=='.'&&s[5][u+3]=='X'&&s[7][u+2]=='X') return 3;
    else if (s[1][u+2]=='.'&&s[4][u+2]=='X'&&s[2][u]=='X'&&s[2][u+3]=='X'&&s[5][u]=='.'&&s[5][u+3]=='X'&&s[7][u+2]=='.') return 4;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='X'&&s[2][u]=='X'&&s[2][u+3]=='.'&&s[5][u]=='.'&&s[5][u+3]=='X'&&s[7][u+2]=='X') return 5;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='X'&&s[2][u]=='X'&&s[2][u+3]=='.'&&s[5][u]=='X'&&s[5][u+3]=='X'&&s[7][u+2]=='X') return 6;
    else if (s[1][u+2]=='X'&&s[4][u+2]=='.'&&s[2][u]=='.'&&s[2][u+3]=='X'&&s[5][u]=='.'&&s[5][u+3]=='X'&&s[7][u+2]=='.') return 7;
    else return 9;

}
int main()
{
    ios::sync_with_stdio(false);
    int  N;
    cin >> N;
    while (N--)
    {
        for (int i = 1; i<=7;i++)
            cin >> s[i];
        cout <<get(0)<<get(5)<<":"<<get(12)<<get(17)<<endl;
    }
    return 0;
}
1011
posted @ 2017-08-03 20:37  myhappinessisall  阅读(187)  评论(0编辑  收藏  举报