zoukankan      html  css  js  c++  java
  • poj杂题选讲

    poj杂题选讲

    poj1147:

    根据最后一列,可以确定答案中0/1的个数,同样第一列也确定了,因为每次操作之后得到的矩阵都是排过序的,不妨考虑一下把最后一列移到第一列,这样可以得到最后一列与第一列排序的对应关系,然后根据这个对应关系就可以知道每一行经过排序会发生什么变化,这样不断递推就可以求出整个矩阵了。由于只需要第一行,输出即可。

    Code
    
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 3e3 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int f[N],nxt[N],ans[N];
    int main(){
        int n = read(),cnt = 0;
        for(int i = 1;i <= n;++i) f[i] = read();
        int tot = 0;
        for(int i = 1;i <= n;++i) if(!f[i]) nxt[++tot] = i;
        for(int i = 1;i <= n;++i) if(f[i]) nxt[++tot] = i;
        for(int i = 1,pos = nxt[1];i <= n;++i) printf("%d ",f[pos]),pos = nxt[pos];
       	puts("");
    	return 0; 
    }
    
    

    poj1163:

    数字三角形,dp入门题。

    [f[x][y] = max(f[x+1][y],f[x+1][y+1])+a[x][y] ]

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 105;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int f[N][N],a[N][N],n;
    int dfs(int x,int y){
        if(f[x][y]) return f[x][y];
        if(x == n) return f[n][y] = a[n][y];
        else return f[x][y] = max(dfs(x + 1,y),dfs(x + 1,y + 1)) + a[x][y];
    }
    int main(){
        n = read();
        for(int i = 1;i <= n;++i) for(int j = 1;j <= i;++j) a[i][j] = read();
        printf("%d
    ",dfs(1,1));
    }
    
    

    poj1922:

    显然这个人一定会跟着骑得最快的人一块骑,因此只需统计出最先到达终点的人的时间即可。注意在0时刻之前出发的,要么一定会被这个人超过,要么永远追不上,所以不予考虑。

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int main(){
        int n;
        while(~scanf("%d",&n) && n){
            double ans = inf;
            for(int i = 1;i <= n;++i){
                double v,t,dt = inf;
                scanf("%lf%lf",&v,&t);
                if(t >= 0) dt = ceil(t + 4.5 / (v / 3600.0));
                ans = min(ans,dt);
            }
            printf("%d
    ",(int)ans);
        }
    }
    

    ​#### poj2211:

    题目大意:给定 (n),$ k$, 求给定排列在所有 (A^k_n) 种排列中的排名的字典序。

    这大概是个高中数学的排列组合问题。得到的排列是 (x_1,x_2,...,x_k),按位考虑即可,对于第(i)个元素,有((x_i-1)A_{n-i}^{k-i})个,当然去个重。

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 25 + 5;
    using namespace std;
    inline LL read() {
    	LL s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    LL fac[N],a[N],T;
    LL A(LL n,LL m){
        if(n < m) return 0;
        return fac[n] / fac[n - m];
    }
    void init(){
    	fac[0] = 1;
        for(LL i = 1;i <= 12;++i) fac[i] = fac[i - 1] * i;
        return ;
    }
    void solve(){
    	for(LL j = 1;j <= T;++j){
            LL n = read(),k = read(),ans = 0;
            for(LL i = 1;i <= k;++i) a[i] = read();
            for(LL i = 1;i <= k;++i){
                ans += (a[i] - 1) * A(n - i,k - i);
                for(int l = i + 1;l <= k;++l) if(a[l] > a[i]) a[l]--;
            }
            printf("Variace cislo %lld ma poradove cislo %lld.
    ",j,ans + 1);
        }
    }
    int main(){
    	T = read();
    	init();
    	solve();
    	return 0;
    }
    
    

    poj2215:

    题目大意:给定一个矩形,内部每个点有权值,多次询问一个子矩形内部权值和。

    二维前缀和了解一下

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e3 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int a[N][N],sum[N][N];
    void init(){
    	memset(a,0,sizeof(a)),memset(sum,0,sizeof(sum));
        int r = read(),s = read();
        for(int i = 1;i <= r;i++) for(int j = 1;j <= s;j++)
        a[i][j] = read(),sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
    }
    void solve(){
    	int q = read();
        while(q--){
            int r1 = read(),s1 = read(),r2 = read(),s2 = read();
            int ans = sum[r2][s2] - sum[r2][s1 - 1] - sum[r1 - 1][s2] + sum[r1 - 1][s1 - 1];
            printf("Absolutni hodnota pohodlnosti je %d bodu.
    ",ans);
        }
        puts("");
    }
    int main(){
        int T = read();
        while(T--){
            init();
            solve();
        }
    }
    

    poj2229:

    题目大意:求一个数 (n) 按照2的幂次拆分的方案数。

    如果(i)是奇数,那么在所有的系列中一定含有一个1,把这个1减掉,就和$i-1¥的对应相等。

    如果(i)是偶数,那么每一项要么都是2以上的数字,要么就一定含有至少两个1。第一种情况,都含有两个1那么就减掉,那么就等于(i-2)对应的值,还有就是全部是2的整数倍,那么不妨直接把2看成1,那是不是相当于数字减少了一半,那么就等于(i/2)对应的值了。

    (O(n))递推就完事了

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int mod = 1000000000; 
    const int N = 2e6 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int f[N];
    int main(){
    	int n = read();
        f[1] = 1,f[2] = 2;
        for(int i = 3;i <= n; i++){
            if(i & 1) f[i] = f[i-1];
            else f[i] =(f[i-1] + f[i>>1]) % mod;
        }
        printf("%d
    ",f[n]); 
        return 0;
    }
    

    poj2232:

    若只有一种手势或有三种手势,则都可以赢,若有两种手势,则克其的能赢。

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int n;
    char ch[2];
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		int a = 0,b = 0,c = 0;
    		for(int i = 0; i < n; i++ ){
    			scanf("%s",ch);
    			if(ch[0] == 'C') a++;
    			if(ch[0] == 'S') b++;
    			if(ch[0] == 'F') c++;
    		}
    		if((a == 0 && b == 0 && c != 0)||(a == 0 && c == 0 && b != 0)||(b == 0 && c == 0 && a != 0)||(a != 0 && b != 0 && c != 0))printf("%d
    ",n);
    		else{
    			if(a == 0) printf("%d
    ",b);
    			else if(b == 0) printf("%d
    ",c);
    			else printf("%d
    ",a);
    		}
    	}
    	return 0 ;
    } 
    
    

    poj2234:

    经典nim游戏,异或值为不为0则先手胜出。

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int n;
    int main(){
    	while(scanf("%d",&n)!=EOF){
    		int ans = 0;
    		for(int i = 1;i <= n;i++){
    			int a = read();
    			ans ^= a;
    		}
    		if(ans) puts("Yes");
    		else puts("No");
    	}
    	return 0;
    }
    
    

    poj2242

    题意:给定圆上3点,求圆的周长

    思路分析:外接圆半径(r = (a*b*c)/(4*S)),其中(a,b,c)为边长,S为三角形面积,(L = 2*pi*r)

    或者是利用圆心为中垂线的交点,求出圆心,然后再求半径也可以。

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    #define eps 1e-6
    #define pi 3.141592653589793
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int main(){
        double x1,x2,x3,y1,y2,y3;
        while(scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3) != EOF){
            double cc = x2-x1,d = y2-y1,e = x3-x1,f = y3-y1;
            double s = fabs(cc*f - d*e);
            s = s/2;
            double a = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
            double b = sqrt((x1-x3)*(x1-x3) + (y1-y3)*(y1-y3));
            double c = sqrt((x2-x3)*(x2-x3) + (y2-y3)*(y2-y3));
            double r = a*b*c/4/s;
            printf("%0.2lf
    ",2*pi*r);
        }
        return 0;
    }
    

    poj2245

    问题大意:给你k个数(递增顺序),从中选择6个数,打印所有的组合方案。k=0表示输入结束,打印时每两个数之间才有空格,并且每个测试之间有一个空行。

    DFS即可

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    const int N=14;
    int vis[N],ans[N],a[N],n;
    void dfs(int i,int k) {
    	if(k == 6){
    		printf("%d",ans[0]);
    		for(int j = 1;j < 6;j++) printf(" %d",ans[j]);
    		puts("");
    		return;
    	}
    	for(;i < n;i++)
    	  	if(!vis[i]){
    	  		vis[i] = 1;
    	  		ans[k] = a[i];
    	  		dfs(i + 1,k + 1);
    	  		vis[i] = 0;
    	  	}
    }
    int main(){
    	bool flag = 0;
    	while(scanf("%d",&n)!=EOF&&n){
    		for(int i=0;i<n;i++) a[i] = read();
    		if(flag) puts("");
    		flag = 1;
    		memset(vis,0,sizeof(vis));
    		dfs(0,0);
    	}
    	return 0;
    }
    
    

    poj2262:

    题目大意:给你一个数n,拆分成两个奇素数相加的形式,另这两个素数的距离最大

    思路:从三开始枚举奇数,判断数(i)(n-i)是否都为素数,若为素数则输出结果。

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 1000000 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int pn[N];
    void init(){
        for(int i = 2; i <= N; i++) pn[i] = 1;
        for(int i = 2; i <= N; i++) if(pn[i]) for(int j = i+i; j <= N; j += i) pn[j] = 0; 
    }
    int main(){
        int n;
        init();
        while(~scanf("%d",&n) && n){
            for(int i = 3; i <=n/2; i+=2){
                if(pn[i] && pn[n-i]){
                    printf("%d = %d + %d
    ",n,i,n-i);
                    break;
                }
            }
        }
        return 0;
    }
    

    poj2301:

    值得注意的是两个数相加或相减的奇偶性是一致的

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int main(){
        int n = read(); 
        while(n--){
            int a = read(),b = read();
            if((a < b) || (a%2==0&&b%2==1)||(b%2==0&&a%2==1)) printf("impossible
    ");
            else printf("%d %d
    ",(a+b)/2,(a-b)/2);
        }
    }
    

    poj2309:

    找规律即可,可以理解为二分查找的过程,我是直接找规律,代码简单

    Code
    #define B cout << "BreakPoint" << endl;
    #define O(x) cout << #x << " " << x << endl;
    #define O_(x) cout << #x << " " << x << " ";
    #define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
    #include<cstdio>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<set>
    #define LL long long
    const int inf = 1e9 + 9;
    const int N = 2e5 + 5;
    using namespace std;
    inline int read() {
    	int s = 0,w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-')
    			w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') {
    		s = s * 10 + ch - '0';
    		ch = getchar();
    	}
    	return s * w;
    }
    int main(){
    	int n = read();
    	while(n--){
    		int s = read();
    		int k=s&(-s);
    		k--;
    		printf("%d %d
    ",s-k,s+k);	
    	}
    	return 0;
    } 
    
  • 相关阅读:
    第4章 排序
    第5章 算术与代数
    第6章 组合数学
    第7章 数论
    第8章 回溯法
    第9章 图遍历
    第11章 动态规划
    第10章 图算法
    第12章 网格
    第13章 几何
  • 原文地址:https://www.cnblogs.com/excellent-zzy/p/12764047.html
Copyright © 2011-2022 走看看