2013-11~ ** 训练小结

2013.12.09
A:  POJ 1306   
算 n!/m!/(n-m)!   1<=n,m<=100   边乘 边除即可 因为, 结果不会超过 __int64 的 
B:  POJ 1742  
起初一看是 多重背包 求方案数 于是按照纯 多重背包写了一下 TLE  之后可以 dp  O(n*m) 可以过 
code:
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
        
        
using namespace std;
#define INF 1000000000
int f[100005];
int sum[100005];
int v[105],c[105];
int main()
{
	//freopen("in.txt","r",stdin);
    int k,n,m;
    while(scanf("%d%d",&n,&m),n||m)
    {
        for(int i = 1; i<=n; i++)
            scanf("%d",&v[i]);
        for(int i = 1; i<=n; i++)
            scanf("%d",&c[i]);
        memset(f,0,sizeof(f));
        f[0] = 1;
        int ans = 0;
        for(int i=1; i<=n; i++)
        {
            memset(sum,0,sizeof(sum));
            for(int j = v[i]; j<=m; j++)
            {
                if(!f[j] && f[j-v[i]] && sum[j-v[i]]
        
        
       
       
      
      
     
     
    
    
C:  HDU 1686  
KMP 待补。。。。
D:  HDU 1213 
并查集  水题
E:  HDU 3863 
其实 ,是一个 很逗的 题目, 两个人游戏, 而且 两个人除了 谁先手外, 其余 的处境 一样, 而且 先手 没有任何 坏处,只有好处,于是没有什么博弈的高级内容,先手的 那个人一定赢, 于是 只有一个字符串输出而已。
F:  POJ 3660  
给定拓扑关系的一部分 ,求 有多少人 的次序可以确定。 智商被压制
建图,floyd 跑一遍,则 可以分别算出, 可以打败他的人数 和 他可以打败的人数 , 如果 相加 等于n-1则 这个人的次序可以确定,反之 同理
#include
      
      
       
       
#include
       
       
        
        
#include
        
        
         
         
#include
         
         
          
          
using namespace std;
#define INF 1000000000
int n,m;
int d[110][110];
int main()
{
	//freopen("in.txt","r",stdin);
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int x,y;
		memset(d,0,sizeof(d));
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&x,&y);
			d[x][y]=1;
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				for(int k=1;k<=n;k++)
				{
					if(d[j][k]) continue;
					if(d[j][i] && d[i][k]) d[j][k]=1;
				}
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			int tmp=0;
			for(int j=1;j<=n;j++)
			{
				if(d[i][j]) tmp++;
				if(d[j][i]) tmp++;
			}
			if(tmp>=n-1) ans++;
		}
		printf("%d\n",ans);
	}

	return 0;
}

         
         
        
        
       
       
      
      
G :  CodeForces 330A  
纯水
n个点 , m条边不可建边, 求 建立最少的边 使得 each point to any point 都可以通过 至多两条边 到达 。
如果看到 题目的 数据范围     这说明, 肯定存在 一个点 可以到 其他任一点建边 不受限制,总边数至少为n-1.
则, 可以从这个 点出发,到其他个点建边即可。。
下面两个题目,没看题。。
J: SPOJ GSS1 



*****************************************************************************************************************************************************************************************
**************************************************************************************************************************************************************************

//[a,b] [c,d] 区间内分别取x,y 使得 (x+y)%p==m成立 给定a,b,c,d,p,m 0<=a<=b<=10^9 c,d同. p,m同样[0,10^9].
// 求 范围内组成等式的概率是多少.
//一共组成的 元素 (b-a+1)*(d-c+1) 个 可以组成矩阵,之后把矩阵的第i行相对于上一行i-1行向右移动一下,使得每列的元素的值相等
//这就形成了一个平行四边形,从左下定点 和右上定点 做垂线,可以分割成两个三角形 和 一个平行四边形(有可能是矩形或者平行四边形)
//两个三角形的 符合条件的元素 随着列数的增加 呈等差数列,矩形则是 每行的符合条件的元素*列数.加一起。求分数即可.
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
using namespace std;
#define INF 1000000005
typedef __int64 LL;
LL a,b,c,d,m,p,l,r;
LL sol(LL x,LL y,int fl)
{
	if(y
       
       
        
        y || l*p+m>y || l*p+m
        
        
          =0? (l-r+1):0; LL a1; if(fl==1) a1=r*p+m-x+1; else if(fl==2) a1=y-l*p-m+1; LL n=l-r+1; return n*a1+n*(n-1)*p/2; } LL gcd(LL x,LL y) { if(y==0) return x; return gcd(y,x%y); } int main() { //freopen("in.txt","r",stdin); int t,time=0; scanf("%d",&t); while(t--) { scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&p,&m); LL tmp1,tmp2,tmp3; if(b+c 
          
        
       
       
      
      
     
     
    
    

// 20000只牛,每个牛在温度区间[A.B]内产奶y,小于A 产奶x,大于B产奶z。对于所有的牛x,y,z都一样每个牛 有A[i],B[i].
//温度区间0-10^9 , 所以要考虑20000只牛 这个小数据,最多有40000个点分割温度区间,由小到大遍历每个区间即可(相对于前一个区间是
//增大还是减小),唯一注意的是 y对应的区间是[A,B],都是闭区间,注意处理[a,b] [b,c] 级边界重合的情况.
/*
ID: tyf19938
LANG: C++
TASK: milktemp
*/
#include
      
      
       
       
#include
       
       
        
        
#include
        
        
         
         
using namespace std;
#define N 20005
int  n,ma,tmp,x,y,z;
struct node
{
	int x,f;
}num[2*N];
bool cmp(node a,node b)
{
	return a.x
         
         
          
          =2*n) break;
			ma=max(ma,tmp);
			if(num[i].x==num[i+1].x) continue;
			tmp+=ad; ad=0;
			ma=max(ma,tmp);
		}
		printf("%d\n",ma);
    }
    return 0;
}

         
         
        
        
       
       
      
      

//给定一个有向图,一共N(N<=50) 个点,给定矩阵 代表从i到j有一条容量为d[i][j]的有向边。给一个数k,可以给任意存在的有向边添加容量
//满足 添加的总容量<=k。 求 点1为源点, 点N 为汇点,的 网络流的最大值.
//建图: 对于d[i][j]!=0的边 添加 一种边为 i->j 容量为 d[i][j] 费用为0 , 另一种 i->j 容量为INF(无穷),费用为1.
//求 source->sink的满足费用<=k的最大流.
#include
      
      
       
       
#include
       
       
        
        
#include
        
        
         
         
#include
         
         
          
          
using namespace std;
#define INF 1000000000
#define N 51
int n,k,pre[N],dis[N],inq[N],tot,hh[N],start,end;
struct node
{
	int u,v,w,c,next;
}edge[6*N*N];
void init()
{
	tot=0;
	memset(hh,-1,sizeof(hh));
}
void add(int u,int v,int w,int c)
{
	edge[tot].u=u; edge[tot].v=v;
	edge[tot].w=w; edge[tot].c=c;
	edge[tot].next=hh[u];
	hh[u]=tot++;
}
int spfa()
{
	queue
          
          
            q; memset(inq,0,sizeof(inq)); memset(pre,-1,sizeof(pre)); for(int i=1;i<=n;i++) dis[i]=INF; dis[start]=0; inq[start]=1; q.push(start); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=hh[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].w && dis[v]>dis[u]+edge[i].c) { pre[v]=i; dis[v]=dis[u]+edge[i].c; if(!inq[v]) { inq[v]=1; q.push(v); } } } inq[u]=0; } if(dis[end]==INF) return -1; return dis[end]; } int maxx() { int re=0; while(1) { int now=spfa(); if(now<0) break; int tmp=INF; for(int i=pre[end];i!=-1;i=pre[edge[i].u]) tmp=min(tmp,edge[i].w); if(k 
            
          
         
         
        
        
       
       
      
      

//给定序列S,可以构成矩阵b  b[i][j]=s[i]*s[j] , 给出a , 求 矩阵b中 多少个矩形块, 其和为a。
//设sum= 第i 到第j 行 和 第x 到第y列 构成的矩形块的和, 可以化简得出: sum=(s[i]+s[i+1]+..+s[j-1]+s[j])*(s[x]+s[x+1]+..+s[y-1]+s[y])
//即求 b=sum的组成个数。 O(n^2)可以枚举出s[i] 到s[j]的 可能取值. 
//之后,对于输入的a, 枚举1~sqrt(a) 的 值f 是否是上面取得的值,而且a%f==0 && a/f也是上面的取值,
//注意, a==0的情况,注意使用64位。
#include
       
       
        
        
#include
        
        
         
         
#include
         
         
          
          
#include
          
          
           
           
#include
           
            using namespace std; typedef __int64 LL; #define INF 1000000000 #define N 4005 LL a,num[N]; char str[N]; map 
            
              m; int main() { scanf("%I64d",&a); scanf("%s",str); m.clear(); num[0]=0; int len=strlen(str); for(int i=0;i 
              
            
          
          
         
         
        
        
       
       

//1000行数据,每行数据范围0~10000,之后有q个(200000)询问,给定两个数a,b , 问是否同时出现在某一行中。
//如果直接开数组[1000][10000],之后对于每个询问,遍历所有的行,会TLE。
//上面数组中存储的 是0 1 矩阵, 每一列是 该数在某行中是否出现,可以把这最多1000位压缩,可以使用bitset或者用32个int拼成1000位。
//[1000][32],这样不仅 内存缩减 而且,查询时 只需要把a 和 b的 1000位(32个int) 取与,出现非零,则该数出现同时出现在某一列中。
//code 1  32个int 拼接。
#include
         
         
          
          
#include
          
          
           
           
#include
           
           
            
            
using namespace std;
#define INF 1000000000
#define N 11000
int d[N][35],n,q;
int main()
{
	//freopen("in.txt","r",stdin);
	while(scanf("%d",&n)!=EOF)
	{
		int tmp,s;
		memset(d,0,sizeof(d));
		for(int i=0;i
            
            
             
             
#include
             
             
               #include 
              
                #include 
               
                 using namespace std; #define INF 1000000000 int n; bitset<1003> d[10003],che; int main() { //freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF) { int x,tmp; for(int i=1;i<=10000;i++) d[i].reset(); for(int i=1;i<=n;i++) { scanf("%d",&x); while(x--) { scanf("%d",&tmp); d[tmp].set(i); } } int q,a,b; scanf("%d",&q); while(q--) { scanf("%d%d",&a,&b); che=d[a]&d[b]; if(che.any()) printf("Yes\n"); else printf("No\n"); } } return 0; } 
                
               
             
            
            
           
           
          
          
         
         


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值