Andrew Stankevich's Contest #补题

ACdream 1210  Chinese Girls' Amusement (规律+数学)

【题意】:

求最大的k<=n/2使得gcd(n,k)=1。

/*
找到与N互质的最大整数K即可。当N为奇数时,(int)(N/2)即为所求数;当N为偶数时,
如果N/2 - 1是奇数,则为所求结果,如果为偶数,N/2 - 2为所求结果
*/

java代码:

//感觉就是暴力  从n/2 开始减 ,直到互素为止, 
import java.io.*;  
import java.util.*;  
import java.math.BigInteger;//声明BigInteger大数类  
import java.lang.*;  

public class Main
{
	public static void main(String args[])
	{
		Scanner cin = new Scanner(System.in);
		BigInteger n,k;
		n=cin.nextBigInteger();
		k=n.divide(new BigInteger("2"));
		while(n.gcd(k).compareTo(BigInteger.ONE)!=0)
		{
			k=k.subtract(BigInteger.ONE);
		}
		System.out.println(k);
	}
}

C++代码:

/*
* this code is made by herongwei
* Problem: 1210
* Verdict: Accepted
* Submission Date: 2015-10-11 10:07:54
* Time: 0MS
* Memory: 1672KB
*/
#include <bits/stdc++.h>
using namespace std;
string ss,ans;
template <class T>
void to_string(string &result,const T&t)
{
    ostringstream oss;//创建一个流
    oss<<t;//把值传入流中
    result=oss.str();
}
void divtwo(const string& ss)// div two
{
    ans="";
    int len=ss.length(),tp;
    tp=ss[0]-'0';
    if(tp>1) ans+=char (tp/2+'0');
    tp&=1;
    for(int i=1; i<len; ++i){
        tp=tp*10+ss[i]-'0';
        ans+=char(tp/2+'0');
        tp&=1;
    }
}
void sub()//sub 1
{
    int i=ans.length()-1;
    while(ans[i]=='0'){
        ans[i]='9';
        --i;
    }
    ans[i]-=1;
}
void print()
{
    int i=0;
    //while(ans[i]=='0') ++i; //qian dao 0
    for(; i<ans.length(); ++i)
        cout<<ans[i];
    cout<<endl;
}
int main()
{
   cin>>ss;
   divtwo(ss);
   if((ss[ss.length()-1]-'0')&1) cout<<ans<<endl;
   else{
       sub();
       if((ans[ans.length()-1]-'0')&1){
           print();
       }
       else{
           sub();
           print();
       }
   }
   return 0;
}


ACdream 1211   Reactor Cooling【上下界网络流 + 输出流量】

题意:

   n个点,及mpipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得mpipe组成一个循环体,里面流躺物质。

并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li

例如:

46(4个点,6pipe)
12 1 3 (1->2上界为3,下界为1)
23 1 3
3 4 1 3
4 1 1 3
1 3 1 3
4 2 1 3

可行流:

 

Andrew Stankevich's Contest #补题_第1张图片

再如:所有pipe的上界为2下界为1的话,就不能得到一种可行流。

 

题解:

上界用ci表示,下界用bi表示。

下界是必须流满的,那么对于每一条边,去掉下界后,其自由流为ci– bi

主要思想:每一个点流进来的流=流出去的流

对于每一个点i,令

Mi= sum(i点所有流进来的下界流)– sum(i点所有流出去的下界流)

如果Mi大于0,代表此点必须还要流出去Mi的自由流,那么我们从源点连一条Mi的边到该点。

如果Mi小于0,代表此点必须还要流进来Mi的自由流,那么我们从该点连一条Mi的边到汇点。

如果求S->T的最大流,看是否满流(S的相邻边都流满)

满流则有解,否则无解。

 

Andrew Stankevich's Contest #补题_第2张图片

代码:

/*
*上下界的网络流,用上界减去下界
* Problem: ACdream 1211
* Running time: 16MS
* Complier: G++
* Author: herongwei
* Create Time: 19:59 2015/10/8 星期四
*/
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;

const int N=250;
const int inf=0x3f3f3f3f;
#define clc(a,b) memset(a,b,sizeof(a));
struct node1
{
    int fm,to,cap,flow;
};
vector <int> v[N];
vector <node1> e;
int vis[N],cnt[N];
void add_edge(int fm,int to,int cap)
{
    e.push_back((node1){fm,to,cap,0});
    e.push_back((node1){to,fm,0,0});
    int tmp=e.size();
    v[fm].push_back(tmp-2);
    v[to].push_back(tmp-1);
}
bool bfs(int s,int t)
{
    clc(vis,-1);
    queue<int> q;
    q.push(s);
    vis[s] = 0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=0;i<v[x].size();i++)
        {
            node1 tmp = e[v[x][i]];
            if(vis[tmp.to]<0 && tmp.cap>tmp.flow)  //第二个条件保证
            {
                vis[tmp.to]=vis[x]+1;
                q.push(tmp.to);
            }
        }
    }
    if(vis[t]>0)return true;
    return false;
}
int dfs(int o,int f,int t)
{
    if(o==t || f==0)  //优化
        return f;
    int a = 0,ans=0;
    for(int &i=cnt[o];i<v[o].size();i++)
    {
        node1 &tmp = e[v[o][i]];
        if(vis[tmp.to]==(vis[o]+1) && (a = dfs(tmp.to,min(f,tmp.cap-tmp.flow),t))>0)
        {
            tmp.flow+=a;
            e[v[o][i]^1].flow-=a; //存图方式
            ans+=a;
            f-=a;
            if(f==0)  //注意优化
                break;
        }
    }
    return ans;  //优化
}
int dinic(int s,int t)
{
    int ans=0;
    while(bfs(s,t))
    {
        clc(cnt,0);
        int f=dfs(s,inf,t);
        ans+=f;
    }
    return ans;
}

int come[N],to[N];
int flow[N][N];
struct node2
{
    int x,y;
} num[N*N];
void init(int n)
{
     for(int i=0;i<=n;i++)
        v[i].clear();
    e.clear();
}
int main()
{
    //freopen("1.txt","r",stdin);
    int _,__;
    while(~scanf("%d%d",&_,&__))
    {
        clc(come,0);
        clc(to,0);
        clc(flow,0);
        int s=0,t = _+1;
        for(int i=0;i<__;i++)
        {
            int x,y,mi,ma;
            scanf("%d%d%d%d",&x,&y,&mi,&ma);
            num[i] = (node2){x,y};
            flow[x][y] += mi;
            add_edge(x,y,ma-mi);
            come[x]+= mi;
            to[y] += mi;
        }
        int s2=0;
        for(int i=1;i<=_;i++)
        {
            int tmp = come[i]-to[i];
            if(tmp<0)
            {
                s2+=(-tmp);
                add_edge(s,i,-tmp);
            }
            if(tmp>0) add_edge(i,t,tmp);
        }
        int ans = dinic(s,t);
        if(ans != s2)
            puts("NO");
        else
        {
            puts("YES");
            for(int i=1;i<=_;i++)
            {
                for(int j=0;j<v[i].size();j++)
                {
                    int f = v[i][j];
                    flow[e[f].fm][e[f].to]+=abs(e[f].flow);
                }
            }
            for(int i=0;i<__;i++)
            {
                printf("%d\n",flow[num[i].x][num[i].y]);
            }
        }
        init(_);
    } return 0;
}
/*
Sample Input

4 6
1 2 1 2
2 3 1 2
3 4 1 2
4 1 1 2
1 3 1 2
4 2 1 2
4 6
1 2 1 3
2 3 1 3
3 4 1 3
4 1 1 3
1 3 1 3
4 2 1 3
Sample Output

NO
YES
1
2
3
2
1
1
*/

ACdream 1213  Matrix Multiplication (数学)
【题意】:

A是图G的关联矩阵,求B=ATA的元素和。

其实就是统计每个数的个数,最后平方求和

代码:

/*
* this code is made by herongwei
* Problem: 1213
* Verdict: Accepted
* Submission Date: 2015-10-06 21:11:02
* Time: 76MS
* Memory: 1712KB
*/
 
#include <bits/stdc++.h>
using namespace std;
int arr[10005];
int main()
{
    int n,m;cin>>n>>m;
    memset(arr,0,sizeof(arr));
    for(int i=0; i<m; ++i)
    {
        int u,v;
        cin>>u>>v;
        arr[u]++;
        arr[v]++;
    }
    int s=0;
    for(int i=1; i<=n; ++i)
        s+=arr[i]*arr[i];
    cout<<s<<endl;
}

ACdream 1216 Beautiful People(二路单调LIS)

【题意】:

选取最多的人,要求不存在两个人i和j,Si <= Sj && Bi >= Bj。

【思路】先把所有人按S升序排序,然后再按B降序排序,对B求最长上升子序列(LIS)。LIS是很经典的问题了,简单的DP复杂度问O(n^2),这里需要使用经典的O(nlg(n))的算法。

代码:

/*
* this code is made by herongwei
* Problem: 1216
* Verdict: Accepted
* Submission Date: 2015-10-08 20:39:41
* Time: 132MS
* Memory: 3632KB
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn=1e5+10;
const int inf=0x3f3f3f3f;
struct node
{
    int x,y,id;
    bool operator <(const node &t) const
    {
        if(x!=t.x) return x<t.x;
        if(y!=t.y) return y>t.y;
    }
} st[maxn];
int dp[maxn];//dp[i]表示最长上升子序列长度为i时子序列末尾的最小B值
int LIS[maxn];//LIS[i]表示以第i个people结尾的最长上升子序列的长度
int main()
{
    //freopen("1.txt","r",stdin);
    int _;
    while(~scanf("%d",&_))
    {
        memset(dp,inf,sizeof(dp));
        memset(LIS,0,sizeof(LIS));
        for(int i=1; i<=_; ++i)
        {
            scanf("%d%d",&st[i].x,&st[i].y);
            st[i].id=i;
        }
        sort(st+1,st+_+1);
        int len=1,ans=1;
        for(int i=1; i<=_; ++i)
        {
            int ck=lower_bound(dp+1,dp+len+1,st[i].y)-dp;//返回大于或等于val的第一个元素位置;
            if(ck==len) len++;
            dp[ck]=st[i].y;
            LIS[i]=ck;
            ans=max(ans,ck);
          //  cout<<"ck= "<<ck<<endl;
          //  cout<<"i= "<<i<<"st[i].x= "<<st[i].x<<"st[i].y= "<<st[i].y<<endl;
          //  cout<<"--------------"<<endl;
        }
       // cout<<"len= "<<len<<endl;
        printf("%d\n",ans);
        for(int i=_; i>=1; --i)
        {
            if(LIS[i]==ans)
            {
                printf("%d",st[i].id);
                if(len!=1) printf(" ");
                ans--;
            }
        }
        puts("");
    }
    return 0;
}

ACdream 1427  Nice Sequence

【题意】:

E - Nice Sequence

Time Limit:  4000/2000MS (Java/Others)     Memory Limit:  128000/64000KB (Java/Others)
Submit  Status

Problem Description

      Let us consider the sequence a1, a2,..., an of non-negative integer numbers. Denote as ci,j the number of occurrences of the number i among a1,a2,..., aj. We call the sequence k-nice if for all i1<i2 and for all j the following condition is satisfied: ci1,j ≥ ci2,j −k. 

      Given the sequence a1,a2,..., an and the number k, find its longest prefix that is k-nice.

Input

      The first line of the input file contains n and k (1 ≤ n ≤ 200 000, 0 ≤ k ≤ 200 000). The second line contains n integer numbers ranging from 0 to n.

Output

      Output the greatest  l such that the sequence a 1, a 2,..., a l is k-nice.

Sample Input

10 1
0 1 1 0 2 2 1 2 2 3
2 0
1 0

Sample Output

8
0
【题意】这道题理解题意很重要,  其实就是当我们从左向右输入一个元素x时,要保证其左侧元素中0-(x-1)出现的次数大于等于 x的出现次数-k,找出这样的最长的前缀。

【思路】:每次输入一个元素,要更新它的次数,还要比较前(x-1)个出现次数的最小值,因此可用线段树维护最小值。只要判断当前x的次数和(前x-1)的次数最小值比较小于K,则break,否则输出查找的最长前缀。

代码:

/*
* 线段树 单点更新,单点查询
* Problem: ACdream No.1427
* Running time: 252MS
* Complier: G++
* Author: javaherongwei
* Create Time: 21:00 2015/10/7
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
const int maxn=200010;
const int inf=0x3f3f3f3f;
inline int max(int a,int b) {return a>b?a:b;}
inline int min(int a,int b) {return a<b?a:b;}
struct node
{
    int left,right,minv,maxv;
    int mid(){
    return (left+right)>>1;
    }
}tree[maxn<<2];
int n,k,sum[maxn<<2];
int arr[maxn],A[maxn];
void build(int l,int r,int rt)
{
    tree[rt].left=l;
    tree[rt].right=r;
    tree[rt].minv=tree[rt].maxv=0;
    if(l==r) return ;
    int m=tree[rt].mid();
    build(l,m,rt*2);
    build(m+1,r,rt*2+1);
}
void update(int pos,int add,int rt)
{
    int l=tree[rt].left;
    int r=tree[rt].right;
    if(l==r)
    {
      tree[rt].minv+=add;
      return ;
    }
    int m=tree[rt].mid();
    if(m>=pos) update(pos,add,rt*2);
    else update(pos,add,rt*2+1);
    tree[rt].minv=min(tree[rt*2].minv,tree[rt*2+1].minv);
}
int query_min(int ql,int qr,int rt)//query(0,arr[ii]-1,1)
{
    int l=tree[rt].left;
    int r=tree[rt].right;
    if(ql<=l&&r<=qr)
    {
        return tree[rt].minv;
    }
    int m=tree[rt].mid();
    int ans1,ans2;
    if(m>=qr)  return query_min(ql,qr,rt<<1);
    else if(m<ql) return query_min(ql,qr,rt<<1|1);
    return min(query_min(ql,qr,rt<<1),query_min(ql,qr,rt<<1|1));
}
int main()
{
    while(~scanf("%d%d",&n,&k))
    {
       memset(arr,0,sizeof(arr));memset(A,0,sizeof(A));
       for(int i=1; i<=n; ++i) scanf("%d",&arr[i]);
       build(0,n,1); 
       int ii;
       for(ii=1; ii<=n; ++ii)
       {
         A[arr[ii]]++;
         update(arr[ii],1,1);
         if(arr[ii]==0) continue;
         int ans=query_min(0,arr[ii]-1,1);
         if(ans<A[arr[ii]]-k) break;
       }
       printf("%d\n",ii-1);
    } return 0;
}
/*
10 1
0 1 1 0 2 2 1 2 2 3
2 0
1 0
Sample Output
8
0
*/<span style="font-family:Arial, Helvetica, sans-serif;">
</span>

  ACdream 1431  Sum vs Product
【题意】:求固定长度为n(2=<n<=500)的且满足集合内所有元素之和恰好等于所有元素之积的集合的个数
【思路】找出前10个,发现规律:对于n(n>2),必然出现这么一个集合{1,1,1,,,,2*n}内
如:

3 {1,2,3}
4 {1,1,2,4}
5 {1,1,1,2,5} {1,1,2,2,2} {1,1,1,3,3}
。。。
集合最大元素必然不超过n,因此后面的元素从n依次递减到2,因此要满足条件,必须要1来补充,发现假如全部填2,则最多填2^9=512>500,即9个2
对于数据范围,可以考虑暴搜
代码:
/*
* DFS
* Problem: ACdrema No.1431
* Running time: 0MS
* Complier: G++
* Author: javaherongwei
* Create Time: 21:00 2015/10/7
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int n,sum;
// 当前可枚举的最大值,深度,当前积,当前和
//剪枝:当前积小于当前和加当前长度则继续搜索
void dfs(int cur,int now_ji,int now_he,int depth){
    for(int i=cur; i>=2; --i){
        if(depth>n) break;
        if(now_ji*i==(now_he+i+n-depth)) sum++;
        else if(now_ji*i<(now_he+i+n-depth))
            dfs(i,now_ji*i,now_he+i,depth+1);
    }
}
int main(){
    while(~scanf("%d",&n)){
        sum=0;
        dfs(n,1,0,1);
        printf("%d\n",sum);
    }
    return 0;
}

详细题解: http://blog.watashi.ws/623/andrew-stankevich-1-solutio/

你可能感兴趣的:(c,比赛总结,Andrew,Stankevichs)