JXNU 2015-11

来源:互联网 发布:笔记本文具 知乎 编辑:程序博客网 时间:2024/06/05 23:31
1001
由于 G 为 a,b 的最大公约数,那么 G 肯定是 a 的约数。由于 L 为 a,b 的最小公倍数,那么 L 肯定是 a 的倍数,也就是说 a 是 L 的约数。
既然 G 是 a 的约数,a 是 L 的约数,那么,G 必然是 L 的约数。如果 L 不能被 G 整除,那么必然不存在满足条件的 a,b
如果 L 能被 G 整除,那么由于 G<=a<=L,G<=b<=L.则满足条件的最小的 a 必然是 G,此时 b 必然等于 L。
故只要判断 L 是否能被 G 整除即可。直接上高精度除法模板,或 JAVA 大数搞之。

1002

首先,m>n 必然会冲突,直接输出 0

考虑 m<=n 的情形,很容易发现 ans=A(n,m)*C(n,m)

1003

直接模拟即可,可以 dfs 实现,也可以直接非递归实现

1004

1001~1004 并不是我出的题,验题的时候我是这样做的,以 O(n^3)的复杂度

暴力出前 20 个数的结果,然后发现有规律,至于规律具体是什么 ,直接
http://oeis.org/之(一个找数列规律的网站,很强大,很多题在推不出公式的情况
下可以这么搞)

1005

难度定位:中等题

归类:数学题
复杂度:O(n)
事实上,行列式可以化简成 a[1]*x^(n-1)+a[2]*x^(n-2)+...+a[n-1]*x^1+a[n]
如果直接算 a[1]*x^(n-1)%mod,需要用快速幂。
这里完全可以以 o(n)的复杂度先预处理出 x^i,(0<=i<=n-1)
然后再以 o(n)的复杂度 ans+=a[i]*x[n-i]即可,(1<=i<=n)

故总复杂度 O(n)

1006
难度定位:中等题
归类:线段树||树状数组
复杂度:O(n*log(n))
由于 i<j<k,a[i]<=a[j]<=a[k]最快的方法便是枚举 a[j],对于 a[j],如果能快速求出前面有多少个数比它小(逆序数),后面有多少个数比它大就好了。恰好,我们可以用线段树维护,并快速求
出。具体做法如下:
第一步,由于数据比较大,故离散化之(离散化三步走,排序,去重,二分)。(这部分复杂度 O(n*log(n)))
第二步,定义 left,right 数组,left[i],意为在 i 前面有多少个数小于等于 a[i],right[i],在 i 后面有多少个数大于等于 a[i]。那么如何求他们呢?例如求 left 数组,
从前往后枚举 i,对于 a[i],假设他离散化后的位置是 p,那么在线段树中查询区间[1,p]的和即可(即为小于等于 a[i]数的个数),然后,更新线段树维护 p 点的区间
的值即可。right 数组求法类似。只不过要从后往前枚举 i。 (这部分也是 O(n*log(n)))
其实上面的做法就是线段树||树状数组求逆序数的思想。
第三步,由乘法原理可知,枚举 i,然后 ans+=left[i]*right[i]即可。(这部分 O(n))
故总复杂度 O(n*log(n))
1007
难度定位:简单题
归类:模拟题
复杂度:O(n)
先把开奖的号码用数组 hash 一下。
对于每组数据与开奖比对,只需要到 hash 数组中查询即可。
1008
难度定位:难题
归类:最小费用最大流
复杂度:O(n^3)
题意:
给定一个有向图,必须用若干个环来覆盖整个图,要求这些覆盖的环的权值最小。
思路:
最小费用最大流,复杂度 O(n^3)
原图每个点 u 拆为 u 和 u' ,从源点引容量为 1 费用为 0 的边到 u ,从u' 引相同性质的边到汇点,若原图中存在 (u, v) ,则从 u 引容量为 1 费用为
c(u, v) 的边到 v' 。这里源模拟的是出度,汇模拟的是入度,又每个点的出度等于入度等于 1 ,那么如果最大流不等于顶点数 n ,则无解;否则,答案就是最小费用。

1001

#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int L=210;int sub(int *a,int *b,int La,int Lb){    if(La<Lb) return -1;//如果a小于b,则返回-1    if(La==Lb)    {        for(int i=La-1;i>=0;i--)            if(a[i]>b[i]) break;            else if(a[i]<b[i]) return -1;//如果a小于b,则返回-1    }    for(int i=0;i<La;i++)//高精度减法    {        a[i]-=b[i];        if(a[i]<0) a[i]+=10,a[i+1]--;    }    for(int i=La-1;i>=0;i--)        if(a[i]) return i+1;//返回差的位数    return 0;//返回差的位数}string div(string n1,string n2,int nn)//n1,n2是字符串表示的被除数,除数,nn是选择返回商还是余数{    string s,v;//s存商,v存余数     int a[L],b[L],r[L],La=n1.size(),Lb=n2.size(),i,tp=La;//a,b是整形数组表示被除数,除数,tp保存被除数的长度     fill(a,a+L,0);fill(b,b+L,0);fill(r,r+L,0);//数组元素都置为0     for(i=La-1;i>=0;i--) a[La-1-i]=n1[i]-'0';     for(i=Lb-1;i>=0;i--) b[Lb-1-i]=n2[i]-'0';     if(La<Lb || (La==Lb && n1<n2)) {            //cout<<0<<endl;     return n1;}//如果a<b,则商为0,余数为被除数     int t=La-Lb;//除被数和除数的位数之差     for(int i=La-1;i>=0;i--)//将除数扩大10^t倍        if(i>=t) b[i]=b[i-t];        else b[i]=0;     Lb=La;     for(int j=0;j<=t;j++)     {         int temp;         while((temp=sub(a,b+j,La,Lb-j))>=0)//如果被除数比除数大继续减         {             La=temp;             r[t-j]++;         }     }     for(i=0;i<L-10;i++) r[i+1]+=r[i]/10,r[i]%=10;//统一处理进位     while(!r[i]) i--;//将整形数组表示的商转化成字符串表示的     while(i>=0) s+=r[i--]+'0';     //cout<<s<<endl;     i=tp;     while(!a[i]) i--;//将整形数组表示的余数转化成字符串表示的</span>     while(i>=0) v+=a[i--]+'0';     if(v.empty()) v="0";     //cout<<v<<endl;     if(nn==1) return s;     if(nn==2) return v;}int main(){    string a,b;    while(cin>>a>>b)    {        //cout<<div(a,b,1)<<endl;        //cout<<div(a,b,2)<<endl;        string ans=div(b,a,2);        if(ans!="0") cout<<-1<<endl;        else cout<<a<<" "<<b<<endl;    }    return 0;}

1002

#include<iostream>#include<cstdio>#define ULL unsigned long longusing namespace std;const int maxn=35;ULL dp[maxn][maxn*maxn];ULL C(int n,int m){    if(n<m) return 0;    ULL ans=1;    for(int i=0;i<m;i++) ans=ans*(ULL)(n-i)/(ULL)(i+1);    return ans;}ULL A(int n,int m){    if(n<m) return 0;    ULL ans=1;    for(int i=0;i<m;i++) ans*=(ULL)(n-i);    return ans;}ULL fuck(int n,int k){    if(dp[n][k]) return dp[n][k];    return dp[n][k]=A(n,k)*C(n,k);}int main(){    //freopen("in.txt","r",stdin);    int n,k,t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&k);        printf("%I64u\n",fuck(n,k));        //printf("%I64u\n",A(n,k));        //printf("%I64u\n",C(n,k));    }    return 0;}

1003

#include<iostream>#include<cstdio>using namespace std;const int maxn=105;int a[maxn][maxn];void dfs(int x,int y,int n,int m,int num){    if(n==0||m==0) return ;    if(n==1)    {        for(int i=0;i<m;i++) a[x][y+i]=num++;        return ;    }    if(m==1)    {        for(int i=0;i<n;i++) a[x+i][y]=num++;        return ;    }    for(int i=0;i<m;i++) a[x][y+i]=num++;    for(int i=1;i<n-1;i++) a[x+i][y+m-1]=num++;    for(int i=m-1;i>=0;i--) a[x+n-1][y+i]=num++;    for(int i=n-2;i>0;i--) a[x+i][y]=num++;    dfs(x+1,y+1,n-2,m-2,num);}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        dfs(0,0,n,m,1);        for(int i=0;i<n;i++)        {            for(int j=0;j<m-1;j++) printf("%d ",a[i][j]);            printf("%d\n",a[i][m-1]);        }    }    return 0;}

1004
<pre name="code" class="cpp">#include<iostream>#include<cstdio>#define LL long longusing namespace std;const int maxn=1000005;LL dp[maxn];int main(){    //dp[0]=1;    //dp[1]=3;    //dp[2]=3;   // for(int i=2;i<maxn;i++) dp[i]=dp[i-2]+(LL)i*(LL)(i-1)/2;    LL n;    while(~scanf("%I64d",&n)) //printf("%d\n",dp[n-3]);    {        n-=4;        LL ans=(n+2)*(n+4)*(2*n+3) / 24;        printf("%I64d\n",ans);    }    return 0;}

1005

<pre name="code" class="cpp">#include<iostream>#include<cstdio>#define LL long longusing namespace std;const int maxn=100005;const LL mod=1000000007;int a[maxn];LL X[maxn];int main(){   // freopen("in.txt","r",stdin);   // freopen("out.txt","w",stdout);    int t,n,x;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&x);        for(int i=1;i<=n;i++) scanf("%d",&a[i]);        X[0]=1;        for(int i=1;i<n;i++) X[i]=(X[i-1]*x)%mod;//预处理出所有的x^i        LL ans=0;        for(int i=0;i<n;i++)            ans=(ans+X[i]*a[n-i])%mod;        printf("%I64d\n",ans);    }    return 0;}


1006

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define LL long long#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int maxn=100005;int a[maxn],b[maxn],Left[maxn],Right[maxn];int sum[maxn<<2];void PushUp(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){    if(l==r)    {        sum[rt]=0;        return ;    }    int m=(l+r)>>1;    build(lson);    build(rson);    PushUp(rt);}void update(int p,int l,int r,int rt){    if(l==r)    {        sum[rt]++;        return ;    }    int m=(l+r)>>1;    if(p<=m) update(p,lson);    else update(p,rson);    PushUp(rt);}int query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)    {        return sum[rt];    }    int m=(l+r)>>1;    int ans=0;    if(L<=m) ans+=query(L,R,lson);    if(R>m) ans+=query(L,R,rson);    return ans;}int main(){   // freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,n;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=0;i<n;i++) scanf("%d",&a[i]),b[i]=a[i];        sort(b,b+n);//离散化第一步        int lb=unique(b,b+n)-b;//离散化第二步        build(1,lb,1);//由于离散化后a[i]的范围为[1,lb],故建立一颗维护[1,lb]的和的线段树        for(int i=0;i<n;i++)        {            int p=upper_bound(b,b+lb,a[i])-b;//离散化第三步            Left[i]=query(1,p,1,lb,1);//查询出小于等于a[i]的数的个数,类似于线段树求逆序数的原理            update(p,1,lb,1);//插入第i个数        }        build(1,lb,1);        for(int i=n-1;i>=0;i--)        {            int p=upper_bound(b,b+lb,a[i])-b;            Right[i]=query(p,lb,1,lb,1);            update(p,1,lb,1);        }        LL ans=0;        for(int i=0;i<n;i++)        {            ans+=(LL)Left[i]*(LL)Right[i];            //printf("%d %d\n",Left[i],Right[i]);        }        printf("%I64d\n",ans);    }    return 0;}
1007
#include<iostream>#include<cstdio>#define LL long longusing namespace std;int a[100005][8];int b[8];int vis[40];int n;int ans[10][10];void SetValue(){    ans[6][1]=5000000;ans[6][0]=500000;    ans[5][1]=3000;ans[5][0]=200;    ans[4][1]=200;ans[4][0]=10;    ans[3][1]=10;ans[2][1]=5;    ans[1][1]=5;ans[0][1]=5;}void solve(){    fill(vis,vis+40,0);    for(int i=0;i<6;i++) vis[b[i]]=1;    LL sum=2*n;    for(int i=0;i<n;i++)    {        int k=0,p;        for(int j=0;j<6;j++) k+=vis[a[i][j]];        p=(a[i][6]==b[6]);        sum-=ans[k][p];    }    printf("%I64d\n",sum);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    SetValue();    int t;    scanf("%d",&t);    while(t--)    {        for(int i=0;i<7;i++) scanf("%d",&b[i]);        scanf("%d",&n);        for(int i=0;i<n;i++)            for(int j=0;j<7;j++)            scanf("%d",&a[i][j]);        solve();    }    return 0;}

1008

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<sstream>#include<fstream>#include<vector>#include<map>#include<stack>#include<list>#include<set>#include<queue>#define LL long long#define lson l,m,rt<<1#define rson m+1,r,rt<<1 | 1using namespace std;const int maxn=100005,inf=1<<29;int n,m,V;typedef pair<int,int>P;struct edge{ int to,cap,cost,rev;};vector<edge>G[maxn];int h[maxn];//¶¥μãμÄêÆint dist[maxn];//×î¶ì¾ààëint prevv[maxn],preve[maxn];void add_edge(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 Dijkstra(int s,int t){    priority_queue<P,vector<P>,greater<P> >q;    fill(dist,dist+V,inf);    dist[s]=0;    q.push(P(0,s));    while(q.size())    {        P p=q.top();q.pop();        int v=p.second;        if(dist[v]<p.first) continue;        for(int i=0;i<G[v].size();i++)        {            edge &e=G[v][i];            if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to])            {                dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];                prevv[e.to]=v;                preve[e.to]=i;                q.push(P(dist[e.to],e.to));            }        }    }}int min_cost_flow(int s,int t,int f){    int res=0;    fill(h,h+V,0);    while(f>0)    {        Dijkstra(s,t);        if(dist[t]==inf) return -1;        for(int v=0;v!=V;v++) h[v]+=dist[v];        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*h[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 main(){    //freopen("in.txt","r",stdin);   // freopen("out.txt","w",stdout);    while(~scanf("%d%d",&n,&m))    {        V=2*n+2;        for(int i=0;i<=V;i++) G[i].clear();        int s=0,t=2*n+1;        for(int i=1;i<=n;i++) add_edge(s,i,1,0);        for(int i=1;i<=n;i++) add_edge(i+n,t,1,0);        while(m--)        {            int x,y,w;            scanf("%d%d%d",&x,&y,&w);            add_edge(x,y+n,1,w);        }        printf("%d\n",min_cost_flow(s,t,n));    }    return 0;}


0 0
原创粉丝点击