您的位置:首页 > 其它

CSU Monthly 2013 Oct.

2013-10-02 21:40 447 查看
题目:CSU Monthly
2013 Oct.

做了不到两个小时就打球去了。虽然没能坚持做完,但是感觉还不错。

A.Small
change

水题。好像就是之前看的关于一个面试题还是什么的。用尽量少的钞票来表示从1到n的值,那么想想二进制原理就知道了。所以这个水题求的是二进制的位数。

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int ans=0;
        while(n)
        {
            n/=2;
            ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}


B.Scoop
water

数学题。裸的catalan。求C(2n,n) - C(2n,n+1) %mod

可以用Lucas定理求,不过mod太大好像没什么优化。直接暴力求逆元也能过。

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
#define mod 1000000007
#define maxn 20010
const long long p=mod;
long long fac[maxn];
long long Pow(long long a,long long b,long long Mod)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
        {
            b--;
            ans=(ans*a)%Mod;
        }
        else
        {
            b/=2;
            a=(a*a)%Mod;
        }
    }
    return ans;
}
void init()
{
    fac[0]=1;
    for(int i=1;i<maxn;i++)
        fac[i]=fac[i-1]*i%p;
}
long long c(long long n,long long m)
{
    if(n<m)
        return 0;
    long long ans=fac
*Pow(fac[n-m]*fac[m]%p,p-2,p)%p;
    return ans;
}
long long Lucas(long long n,long long m)
{
    if(m==0)
        return 1;
    return Lucas(n/p,m/p)*c(n%p,m%p)%p;
}
long long solve(int n)
{
    long long ans=c(2*n,n)-c(2*n,n+1);
    return (ans%mod+mod)%mod;
}
int main()
{
    init();
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        printf("%lld\n",solve(n)%mod);
    }
    return 0;
}


C.CX‘s
dreams

标程说是最大权闭合子图。图论题,不会。

D.CX
and girls

最短路。wiking大神敲的。

// wiking
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#include<iostream>
using namespace std;
const int maxn = 10000 + 5;
const int INF = 1000000000;
typedef long long LL;
typedef pair<int,int> P;
 
int n,m;
struct Edge{
    int from,to,dis;
}e[maxn*2];
 
int d[maxn];
int vis[maxn];
vector<Edge> G[maxn];
 
void Dij(int x){
    priority_queue<P,vector<P>,greater<P> > Q;
    memset(vis,0,sizeof(vis));
    for(int i = 0;i <= n;i++) d[i] = INF;
    Q.push(P(0,x));
    while(!Q.empty()){
        P p = Q.top();Q.pop();
        int id = p.second;
        LL dis = p.first;
        if(vis[id] == 1) continue;
        vis[id] = 1;
        d[id] = dis;
        for(int i = 0;i < G[id].size();i++){
            Edge edgs = G[id][i];
            int to = edgs.to;
            LL der = edgs.dis;
            if(d[to] > d[id] + der){
                d[to] = d[id] + der;
                Q.push(P(d[to],to));
            }
        }
    }
}
 
int a[maxn];
int dp[maxn];
 
int dfs(int x){
    if(dp[x] != -1) return dp[x];
    if(x == 1) return dp[x] = a[x];
    int Max = 0;
    for(int i = 0;i < G[x].size();i++){
        Edge edges = G[x][i];
        int to = edges.to;
        int dis = edges.dis;
        if(d[to]+dis == d[x]) Max = max(Max,dfs(to));
    }
    return dp[x] = a[x]+Max;
}
 
int main(){
    while(scanf("%d%d",&n,&m) != EOF){
        for(int i = 0;i <= n;i++) G[i].clear();
        for(int i = 1;i <= n;i++){
            scanf("%d",&a[i]);
        }
        for(int i = 0;i < m;i++){
            scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].dis);
            e[i+m].from = e[i].to;e[i+m].to = e[i].from;e[i+m].dis = e[i].dis;
            G[e[i].from].push_back(e[i]);
            G[e[i].to].push_back(e[i+m]);
        }
        Dij(1);
        if(d
 == INF){
            printf("-1\n");
            continue;
        }
        memset(dp,-1,sizeof(dp));
        printf("%d\n",dfs(n));
    }
    return 0;
}


E.ZZY‘s
new company

题解说是线段树+倍增法查找最近公共祖先,不会做。

F.ZZY
and his little friends

判断抑或的最大值是否大于m,字典树

#include <stdio.h>
#include <string.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define NODE 3200010
#define N 100010
int n;
int v
;
int node;
int next[NODE][2];
int end[NODE];
void add(int cur,int k)
{
    memset(next[node],0,sizeof(next[node]));
    end[node]=0;
    next[cur][k]=node++;
}
int cal(int x)
{
    int i,k,cur=0;
    for(i=30;i>=0;i--)
    {
        k=((1<<i)&x)?0:1;
        if(next[cur][k]) cur=next[cur][k];
        else    cur=next[cur][1-k];
    }
    return (x^end[cur]);
}
int main()
{
    int i,j,k,x,cur;
    long long ans;
    long long mm;
    while(~scanf("%d%lld",&n,&mm))
    {
        node=1;
        memset(next[0],0,sizeof(next[0]));
        for(i=0;i<n;i++)
        {
            scanf("%d",&x);
            v[i]=x;
            cur=0;
            for(j=30;j>=0;j--)
            {
                k=((1<<j)&x)?1:0;
                if(next[cur][k]==0) add(cur,k);
                cur=next[cur][k];
            }
            end[cur]=x;
        }
        for(ans=i=0;i<n;i++)    ans=MAX(ans,cal(v[i]));
        if(ans>mm)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}


G.Apple
tree

树形依赖背包,不会。

H.A
very hard problem

//数论题。。。还在做。。A了再把代码粘过来吧。

好吧。。。这题过不了。。。倍数问题很简单就是(x/p)*(y/p),约数的问题,方法是对p质因数分解之后求出p的所有约数,然后对每个约数的处理同 hdu 1695 稍微有点点不同,自己改下应该就ok,==,由于基本上不会莫比乌斯反演,我改了好久也改不对,pass吧。

I.The
contest

分组背包。小建建A了,贴个代码。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
 
int p[1011];
int find(int x)
{
    if(p[x]!=x) return p[x]=find(p[x]);
    return x;
}
 
int dp[1011];
int n,Wmax,k,a,b;
int P[1011],W[1011];
map<int,int>root;
vector<int>e[1011];
int main()
{
    while(~scanf("%d%d%d",&n,&Wmax,&k))
    {
        int r=1;
        root.clear();
        for(int i=1;i<=n;i++) p[i]=i,e[i].clear();
        for(int i=1;i<=n;i++) scanf("%d%d",&P[i],&W[i]);
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d",&a,&b);
            int A=find(a),B=find(b);
            if(p[A]!=B) p[A]=B;
        }
        for(int i=1;i<=n;i++)
        {         
            int x=find(i);
            if(root[x]==0) root[x]=r++;
            e[root[x]].push_back(i);
        }
        //  printf("%d %d\n",e[1][0],e[1][1]);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<r;i++)
            for(int v=Wmax;v>=0;v--)
                for(int j=0;j<e[i].size();j++)
                {
                    int x=e[i][j];
                    if(v<W[x]) continue;
                    dp[v]=max(dp[v],dp[v-W[x]]+P[x]);
                }
 
        printf("%d\n",dp[Wmax]);
    }
}


J.Scholarship

贪心,思维题。小建建先A了,我赛后A掉了。

// 小建建
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
 
int n;
 
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        char s[12],s1[12];
        char ans[12];
        int b;
        scanf("%d",&b);
        if(b<0) 
        {
            printf("0\n");
            continue;
        }
        b++;
        int l=0;
        while(b)
        {
            s1[l++]=b%10+'0';
            b/=10;
        }
        s1[l]='\0';
        l=strlen(s1);
        for(int i=0;i<l;i++)
        {
            s[l-1-i]=s1[i];
        }
        s[l]='\0';
        //printf("%s  z\n",s);
        if(l==1)
        {
            printf("%s\n",s);
        }
        else
        {
            while(1)
            {
                int tag=-1;
                for(int i=1;s[i];i++)
                {
                    if(s[i]!='0'&&s[i]==s[i-1])
                    {
                        tag=i;break;
                    }
                }
                if(tag==-1)
                {
                    printf("%s\n",s);
                    break;
                }
                int r,a=1;
                for(int i=tag+1;s[i];i++) s[i]='0';
                for(int i=tag;i>=0;i--)
                {
                    a+=s[i]-'0';
                    if(a<=9)
                    {
                        r=0;
                        s[i]=a+'0';break;
                    }
                    else
                    {
                        r=1;
                        s[i]=a%10+'0';
                        a/=10;
                    }
                }
                if(r)
                {
                    ans[0]='1';
                    for(int i=0;s[i];i++)
                        ans[i+1]=s[i];
                    ans[l+1]='\0';
                }
                else
                {
                    for(int i=0;s[i];i++) ans[i]=s[i];
                    ans[l]='\0';
                }
                strcpy(s,ans);
            }
        }
    }
    return 0;
}


// mine
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <strstream>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int i;
        string s="";
        int num;
        cin>>num;
        if(num<0)
        {
            printf("0\n");
            continue;
        }
        if(num==0)
        {
            printf("1\n");
            continue;
        }
        num++;
        strstream ss;
        ss << num;
        ss >> s;
        int cnt=s.size()-1;
        bool pika=true;
        while(pika){
            int index=s.size();
            for(i=1;i<s.size();i++)
            {
                if(s[i]==s[i-1] && s[i]!='0')
                {
                    index=i;
                    break;
                }
            }
            if(index==s.size())
            {
                cout<<s<<endl;
                pika=false;
                continue;
            }
            cnt=index;
            int remain=1;
            bool ok=false;
            while(cnt>=0)
            {
                if(s[cnt]=='9' && remain==1)
                {
                    if(cnt==0)
                        ok=true;
                    s[cnt]='0';
                    cnt--;
                }
                else if(remain)
                {
                    s[cnt]++;
                    remain=0;
                    cnt--;
                }
                else
                    break;
            }
            for(int i=index+1;i<s.size();i++)
                s[i]='0';
            if(ok)
            {
                s="1"+s;
            }
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: