HPU 周练一

37 篇文章 0 订阅
36 篇文章 1 订阅

HDU - 2709
Farmer John commanded his cows to search for different sets of numbers that sum to a given number. The cows use only numbers that are an integer power of 2. Here are the possible sets of numbers that sum to 7:

1) 1+1+1+1+1+1+1
2) 1+1+1+1+1+2
3) 1+1+1+2+2
4) 1+1+1+4
5) 1+2+2+2
6) 1+2+4

Help FJ count all possible representations for a given integer N (1 <= N <= 1,000,000).
Input
A single line with a single integer, N.
Output
The number of ways to represent N as the indicated sum. Due to the potential huge size of this number, print only last 9 digits (in base 10 representation).
Sample Input
7
Sample Output
6
递推,
n= 4
1 1 1 1
1 1 2
2 2 。。。 4

n=5
1 1 1 1
1 1 1 2
1 2 2 。。。 4

n= 6
1 1 1 1 1 1
1 1 1 1 2
1 1 2 2 。。。 1 1 4
2 2 2 。。。。2 4
从上述种可以看到 没加一个数字,都是只有最后一行的不同,多加了一个2或者一个1.
如果 n为奇数,就是为dp[n]=dp[n-1].
否则, 就是 dp[n-1]+最后一行的2的个数,来继续数。
其实可以发现
n 个1 和 n 个 2 ,能够继续向上加的个数应该是一样的。
所以此时 dp[n] =dp[n-1]+dp[n/2] .
代码

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 1e6+10;
const int MAXM = 1e6;
const int mod = 1e9;
const int inf = 0x3f3f3f3f;

int dp[MAXN]={0,1,2,2,4,4};
void init(){
    for(int i=6;i<MAXN;i++)
        if(i&1) dp[i]=dp[i-1];
        else dp[i]=(dp[i-1]+dp[i/2])%mod;
}
int main(){
    CLOSE();
//  fread();
//  fwrite();
    int n;
    init();
    while(cin>>n){
        printf("%d\n",dp[n]);
    }
    return 0;
}

51Nod - 1279
有一口井,井的高度为N,每隔1个单位它的宽度有变化。现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住(恰好等于的话会下去)。
盘子有几种命运:1、掉到井底。2、被卡住。3、落到别的盘子上方。
盘子的高度也是单位高度。给定井的宽度和每个盘子的宽度,求最终落到井内的盘子数量。

如图井和盘子信息如下:
井:5 6 4 3 6 2 3
盘子:2 3 5 2 4

最终有4个盘子落在井内。
本题由 @javaman 翻译。
Input
第1行:2个数N, M中间用空格分隔,N为井的深度,M为盘子的数量(1 <= N, M <= 50000)。
第2 - N + 1行,每行1个数,对应井的宽度Wi(1 <= Wi <= 10^9)。
第N + 2 - N + M + 1行,每行1个数,对应盘子的宽度Di(1 <= Di <= 10^9)
Output
输出最终落到井内的盘子数量。
Sample Input
7 5
5
6
4
3
6
2
3
2
3
5
2
4
Sample Output
4

二分 ,虽然给定的序列不是有序的,但是仔细想一下就知道,其实是有序的,嘿嘿。 可以自己想想。
看代码

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 50000+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

int a[MAXN],b[MAXN];

int main(){
    CLOSE();
//  fread();
//  fwrite();
    int n,m;
    while(cin>>n>>m){
        int tot=0; int minn=inf; 
        int k;
        for(int i=1;i<=n;i++) {
            int temp;cin>>temp;

            if(temp<minn) {
                minn=temp;
                k=temp;
                a[tot++]=-temp;
            }else {
                a[tot++]=-k;
            }
        }
        //for(int i=0;i<tot;i++) printf("%/d ",a[i]);
        for(int i=1;i<=m;i++) cin>>b[i];

        int ans=0;int pos=tot;
        for(int i=1;i<=m;i++) {
            pos=upper_bound(a,a+pos,-b[i])-a;
            if(pos>0){
                 ans++;
                 //printf(" pos==%d\n",pos);
            }
            pos--;if(pos<=0) break;
        }
        printf("%d\n",ans);
    }
    return 0;
}

51Nod - 1315
一个整数集合S是合法的,指S的任意子集subS有Fun(SubS)!=X,其中X是一个固定整数,Fun(A)的定义如下:
A为一个整数集合,设A中有n个元素,分别为a0,a1,a2,…,an-1,那么定义:Fun(A)=a0 or a1 or … or an-1;Fun({}) = 0,即空集的函数值为0.其中,or为或操作。
现在给你一个集合Y与整数X的值,问在集合Y至少删除多少个元素能使集合Y合法?

例如:Y = {1,2,4},X=7;显然现在的Y不合法,因为 1 or 2 or 4 = 7,但是删除掉任何一个元素后Y将合法。所以,答案是1.
Input
第一行两个整数N,X,其中N为Y集合元素个数,X如题所述,且1<=N<=50,1<=X<=1,000,000,000.
之后N行,每行一个整数yi,即集合Y中的第i个元素,且1<=yi<=1,000,000,000.
Output
一个整数,表示最少删除多少个元素。
Sample Input
5 7
1
2
4
7
8
Sample Output
2
思维,找规律
代码有点丑,
代码

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 100;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

bool bit[MAXN][50]={0};// 每一个用二进制表示都存了进去。
int gee[MAXN];
bool ans[50]={0};
int main(){
//  CLOSE();
//      fread();
//      fwrite();
    int n,x;
    scanf("%d%d",&n,&x);

        int cnt=0;  int tot=1; 
    for(int i=1;i<=n;i++ ){
        int a;   scanf("%d",&a);
        if(a==x) cnt++;
        else {
            int ge=0;
            while(a){
                if(a&1) bit[tot][ge++]=1;
                else bit[tot][ge++]=0;
                a>>=1;
            }
            gee[tot]=ge;

//          for(int i=0;i<ge;i++) printf("%d ",bit[tot][i]);
//          puts("");
            tot++;
        }
    }
    int ge=0;
    while(x){
        if(x&1) ans[ge++]=1;
        else ans[ge++]=0;
        x>>=1;
    }

//  for(int i=0;i<ge;i++) printf("%d ",ans[i]);
//  puts("");
    for(int i=0;i<ge;i++){
        for(int j=1;j<tot;j++){
            if(ans[i]==0&&bit[j][i]==1) memset(bit[j],0,sizeof(bit[j]));
        }
    }

    int mincnt=inf;
    for(int i=0;i<ge;i++){
        int a,b; a=b=0;

        for(int j=1;j<tot;j++){
            if(ge<gee[j])  continue ;
             if(bit[j][i]) a++;
             else b++;
        }

        if(ans[i]) {
            if(a) {
                mincnt=min(mincnt,a);
            }
            else {
                printf("%d\n",cnt);
                return 0;
            }
        }else {
            if(b) {
            //  mincnt=min(mincnt,b);
            }else {
                printf("%d\n",cnt);
                return 0; 
            }
        }
    }
    printf("%d\n",cnt+mincnt);
    return 0;
}

CodeForces - 670D1
This problem is given in two versions that differ only by constraints. If you can solve this problem in large constraints, then you can just write a single solution to the both versions. If you find the problem too difficult in large constraints, you can write solution to the simplified version only.

Waking up in the morning, Apollinaria decided to bake cookies. To bake one cookie, she needs n ingredients, and for each ingredient she knows the value ai — how many grams of this ingredient one needs to bake a cookie. To prepare one cookie Apollinaria needs to use all n ingredients.

Apollinaria has bi gram of the i-th ingredient. Also she has k grams of a magic powder. Each gram of magic powder can be turned to exactly 1 gram of any of the n ingredients and can be used for baking cookies.

Your task is to determine the maximum number of cookies, which Apollinaria is able to bake using the ingredients that she has and the magic powder.

Input
The first line of the input contains two positive integers n and k (1 ≤ n, k ≤ 1000) — the number of ingredients and the number of grams of the magic powder.

The second line contains the sequence a1, a2, …, an (1 ≤ ai ≤ 1000), where the i-th number is equal to the number of grams of the i-th ingredient, needed to bake one cookie.

The third line contains the sequence b1, b2, …, bn (1 ≤ bi ≤ 1000), where the i-th number is equal to the number of grams of the i-th ingredient, which Apollinaria has.

Output
Print the maximum number of cookies, which Apollinaria will be able to bake using the ingredients that she has and the magic powder.

Example
Input
3 1
2 1 4
11 3 16
Output
4
Input
4 3
4 3 5 6
11 12 14 20
Output
3
Note
In the first sample it is profitably for Apollinaria to make the existing 1 gram of her magic powder to ingredient with the index 2, then Apollinaria will be able to bake 4 cookies.

In the second sample Apollinaria should turn 1 gram of magic powder to ingredient with the index 1 and 1 gram of magic powder to ingredient with the index 3. Then Apollinaria will be able to bake 3 cookies. The remaining 1 gram of the magic powder can be left, because it can’t be used to increase the answer.
水题,模拟就好
代码

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 1000+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

int val[MAXN];
int have[MAXN];
int main(){
    CLOSE();
//  fread();
//  fwrite();
    int n,k;cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>val[i];
    for(int i=1;i<=n;i++) cin>>have[i];
    int cnt=0;
    while(1){
        int flag=1;
        for(int i=1;i<=n;i++){
            if(have[i]>=val[i]) have[i]-=val[i];
            else {
                if(val[i]-have[i]<=k) {
                    k=k-(val[i]-have[i]); 
                    have[i]=0; 
                }else {
                    flag=0;break;
                }
            }
        }
        if(flag) cnt++;
        else break;
    }
    printf("%d\n",cnt);
    return 0;
}

51Nod - 109
给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等。从中找出所有和 = 0的3个数的组合。如果没有这样的组合,输出No Solution。如果有多个,按照3个数中最小的数从小到大排序,如果最小的数相等则按照第二小的数排序。
Input
第1行,1个数N,N为数组的长度(0 <= N <= 1000)
第2 - N + 1行:Aii(-10^9 <= Aii <= 10^9)
Output
如果没有符合条件的组合,输出No Solution。
如果有多个,按照3个数中最小的数从小到大排序,如果最小的数相等则继续按照第二小的数排序。每行3个数,中间用空格分隔,并且这3个数按照从小到大的顺序排列。
Sample Input
7
-3
-2
-1
0
1
2
3
Sample Output
-3 0 3
-3 1 2
-2 -1 3
-2 0 2
-1 0 1
听说别人暴力也是可以过的,我是用的二分/。

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 1000+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

int n;
LL arr[MAXN];
LL brr[4];
int main(){
    CLOSE();
//  fread();
//  fwrite();
     while(cin>>n){

        for(int i=0;i<n;i++) cin>>arr[i];
        sort(arr,arr+n);
        int flag=0; 
        for(int i=0;i<n;i++){
            for(int j=i+1;j<n;j++){
                LL sum=arr[i]+arr[j];
                int pos=lower_bound(arr,arr+n,-sum)-arr;
                if(pos<=j) continue; if(arr[pos]!=-sum) continue;
                flag=1;
                brr[0]=arr[i];brr[1]=arr[j];brr[2]=arr[pos];
                sort(brr,brr+3);
                printf("%lld %lld %lld\n",brr[0],brr[1],brr[2]);
              }
          }
        if(!flag) puts("No Solution");
     }
    return 0;
}

51Nod - 1079
一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
Input
第1行:1个数N表示后面输入的质数及模的数量。(2 <= N <= 10)
第2 - N + 1行,每行2个数P和M,中间用空格分隔,P是质数,M是K % P的结果。(2 <= P <= 100, 0 <= K < P)
Output
输出符合条件的最小的K。数据中所有K均小于10^9。
Sample Input
3
2 1
3 2
5 3
Sample Output
23
中国剩余定理的模板题,不会,后补的,模板 记住吧。

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 100+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

int n;
LL a[MAXN],m[MAXN];
LL gcd(LL a,LL b){
    return b==0?a:gcd(b,a%b);
}
void exgcd(LL a,LL b,LL d,LL &x,LL &y){
    if(!b) {
        d=a; x=1; y=0;
    }else {
        exgcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
LL CRT(){
    LL M=1,d,x,y;x=0;
    for(LL i=1;i<=n;i++) 
        M=M/gcd(M,m[i])*m[i];
    for(LL i=1;i<=n;i++){
        LL w=M/m[i];
        exgcd(m[i],w,d,d,y);
        x=(x+y*w*a[i])%M;
    }
    return (x+M)%M;
}
int main(){
    CLOSE();
//  fread();
//  fwrite();
    while(cin>>n){
        for(int i=1;i<=n;i++ ) cin>>m[i]>>a[i];
        printf("%lld\n",CRT());
    }
    return 0;
}

51Nod - 1264
给出平面上两条线段的两个端点,判断这两条线段是否相交(有一个公共点或有部分重合认为相交)。 如果相交,输出”Yes”,否则输出”No”。
Input
第1行:一个数T,表示输入的测试数量(1 <= T <= 1000)
第2 - T + 1行:每行8个数,x1,y1,x2,y2,x3,y3,x4,y4。(-10^8 <= xi, yi <= 10^8)
(直线1的两个端点为x1,y1 | x2, y2,直线2的两个端点为x3,y3 | x4, y4)
Output
输出共T行,如果相交输出”Yes”,否则输出”No”。
Sample Input
2
1 2 2 1 0 0 2 2
-1 1 1 1 0 0 1 -1
Sample Output
Yes
No
手抄了一份kuangbin的板子。

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 1e5;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

const double eps =1e-8;
const double PI=acos(-1.0);
int sgn(double x){
    if(fabs(x)<eps) return 0;
      if(x<0) return -1;
      else return 1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x=_x;y=_y;
    }
    Point operator  - (const Point &b)const {
    return Point(x-b.x,y-b.y);
    }
    double operator  ^ (const Point &b)const {
    return x*b.y-y*b.x;
    }
    double operator *(const Point &b)const {
            return x*b.x+y*b.y;
    }
};
struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e){
        s=_s;e=_e;
    }
};
bool inter (Line l1,Line l2){
    return 
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)&&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)&&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)&&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)&&
    sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <=0 &&
    sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <=0 ;
}
int main(){
    CLOSE();
//  fread();
//  fwrite();

    int T; cin>>T;
    while(T--){
        Point a,b,d,c;
        cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>d.x>>d.y;
        Line l1; l1.s=a;l1.e=b;
        Line l2; l2.s=c;l2.e=d;

        if(inter(l1,l2)) puts("Yes");
        else puts("No");

    } 
    return 0;
}

51Nod - 1414
白兰大学正在准备庆祝成立256周年。特别任命副校长来准备校园的装扮。

校园的中心竖立着n个冰雕。这些雕像被排在一个等分圆上,因此他们形成了一个正n多边形。这些冰雕被顺针地从1到n编号。每一个雕有一个吸引力tii.

校长来看了之后表示不满意,他想再去掉几个雕像,但是剩下的雕像必须满足以下条件:

・ 剩下的雕像必须形成一个正多边形(点数必须在3到n之间,inclusive),

・ 剩下的雕像的吸引力之和要最大化。

请写一个程序帮助校长来计算出最大的吸引力之和。如果不能满足上述要求,所有雕像不能被移除。

Input
单组测试数据。
第一行输入一个整数n(3≤n≤20000),表示初始的冰雕数目。
第二行有n个整数t11,t22,t33,…,tnn,表示每一个冰雕的吸引力(-1000≤tii≤1000),两个整数之间用空格分开。
Output
输出答案占一行。
Sample Input
8
1 2 -3 4 -5 5 2 3
6
1 -2 3 -4 5 -6
Sample Output
14
9
数学+思维+暴力
找几个看看,就知道,一个n变形,它可以变成几种 正多边形,弄清楚这一点就会写了。

#include<bits/stdc++.h>
using namespace std;
#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 20000+10;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;

int  arr[MAXN*2];
int main(){
    CLOSE();
//  fread();
//  fwrite();
    int n;
    while(cin>>n){
    int ans=0;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
        arr[i+n]=arr[i];
        ans+=arr[i];
    }

//  printf("ans==%d\n",ans);
    /*
    8
    1 2 -3 4 -5 5 2 3 1 2 -3 4 -5 5 2 3 
    */
    int a,b;
    if(n%2==0){
        if(n/2<3) {
            printf("%d\n",ans);
            continue;
          }  
        b=2;a=n/2;
        for(int j=1;j<=b;j++){
                int temp=0;
                for(int k=1;k<=a;k++){
                    temp+=arr[j+k*2];
                }
                ans=max(ans,temp);
            }   
    }

    for(int i=3;i*i<=n;i++){
        if(n%i==0){
            a=min(n/i,i);  b=max(n/i,i);   
            for(int j=1;j<=b;j++){
                int temp=0;
                for(int k=1;k<=a;k++){
                    temp+=arr[j+k*i];
                }
                ans=max(ans,temp);
            }
            swap(a,b);
            for(int j=1;j<=b;j++){
                int temp=0;
                for(int k=1;k<=a;k++){
                    temp+=arr[j+k*i];
                }
                ans=max(ans,temp);
            }
        }
    }
    printf("%d\n",ans);
    }
    return 0;
}

51Nod - 1403
大家都熟悉堆栈操作。一个堆栈一般有两种操作,push和pop。假设所有操作都是合法的并且最终堆栈为空。我们可以有很多方法记录堆栈的操作,
(1) 对每个pop操作,我们记录它之前一共有多少个push操作。
(2) 对每个pop操作,我们记录这个被Pop的元素曾经被压上了几个。
例如:操作push, push, pop, push, push, pop, push, pop, pop, pop
用第一种方法 记录为 2, 4, 5, 5, 5
用第二种方法 记录为 0, 0, 0, 2, 4
这两种记录方法可以互相转化,我们的问题是,给定第二种记录方法的序列,请求出第一种记录方法的序列。

Input
第一行一个整数n,表示序列的长度(0 < n <=1000000)
第二行n个整数,表示第二种方法的记录。
Output
一行,空格分隔的n个整数,表示第一种表示方法的序列。
Sample Input
5
0 0 0 2 4
Sample Output
2 4 5 5 5

思维,
对于每次的pop,如果为a,那我们就知道,它的前面一定会有a个push和a个pop,我第一定按照push写,一直TLE,后来改为了pop写,pop是不会动的,时间复杂度很小。
标记好每个pop的位置,记录数目就可以过。

代码
还有一点,头文件不要写成cstdio 否则TLE。

#include<stdio.h>

#define  LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)

const int MAXN = 1e6+100;
const int MAXM = 1e6;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;


inline int read(){
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') {  ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int a[MAXN];
int main(){
//  fread();
//  fwrite();
    int n;
    n=read();
    int val;
    for(int i=1;i<=n;i++) {
        val=read();
        if(val) a[i-val]++;
        else a[i]=1;
    }
    a[0]=0;
    for(int i=1;i<=n;i++)  a[i]=a[i]+a[i-1];
    int have=0;
    for(int i=1;i<=n;i++){
        printf("%d%s",a[i],i!=n?" ":"");
    } 
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值