zoukankan      html  css  js  c++  java
  • USACO1.4 1.5 搜索剪枝与数字 洛谷OJ P1214 P1215 P1217 P1218

    USACO1.4 题解

    Arithmetic Progressions

    题意

    让你求长为n的由小于2*m*m的双平方数组成的等差数列有几个

    双平方数:形如 B=P*P+Q*Q,p,q>0的数


    题解

    枚举首项和公差,判n个数是否为等差数列,复杂度为m^4

    m*m/(n-1)为公差的枚举次数,m*m为首项的结局次数,n为数列的枚举次数,其中还可以剪枝一下,如果数列的最后一项大于2*m*m,就break;

    另一个优化是枚举前两个双平方数,算出首项公差,双平方的数量级是2e4,


    代码

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <set>
    #include<algorithm>
    #include<map>
    typedef long long ll;
    using namespace std;
    #define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
    #define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
    #define md(x) x=(x+mod)%mod
    #define pb push_back
    
    #define pii pair<int,int>
    #define x first
    #define y second
    
    
    int smain();
    #define ONLINE_JUDGE
    
    int main() {
    	//ios::sync_with_stdio(false);
    #ifdef ONLINE_JUDGE
    	FILE *myfile;
    	myfile = freopen("ariprog.in", "r", stdin);
    	if (myfile == NULL)
    		fprintf(stdout, "error on input freopen
    ");
    	FILE *outfile;
    	outfile = freopen("ariprog.out", "w", stdout);
    	if (outfile == NULL)
    		fprintf(stdout, "error on output freopen
    ");
    
    #endif
    	smain();
    
    	return 0;
    }
    const int maxn = 13;
    
    #define FAST_IO ios_base::sync_with_stdio(false); cin.tie(nullptr)
    
    
    
    int n;
    int m;
    
    int cnt[130000];
    vector<pii> ans;
    vector<int> V;
    int smain() {
    	FAST_IO;
    	cin >> n>>m;
    	rep(i, 0, m)rep(j, 0, m) {
    		cnt[i*i + j * j]++;
    	}
    	int mm = m * m * 2;
    	rep(i, 0, mm)if (cnt[i])V.push_back(i);
    	int a, b;
    	sort(V.begin(), V.end());
    	rep(i, 0, V.size() - n+1) {
    		rep(j, i+1, V.size() - n+1) {
    			 a = V[i]; b = V[j] - V[i];
    			 if (a + (n - 1)*b > mm)continue;
    			 //if (b <= 0)continue;
    			 int ok = 1;
    			 per(k,n-2,1) {
    				 int ai = V[j] + b * k;
    				 if (ai > mm) { ok = 0; break; }
    				 if(cnt[ai] == 0) { ok = 0; break; }
    			 }
    			 if (ok)ans.push_back({ b,a });
    		}
    
    	}
    	sort(ans.begin(), ans.end());
    	if(ans.empty())cout<<"NONE"<<endl;
    	for (auto t : ans) {
    		cout << t.y <<' '<< t.x << endl;
    	}
    	cin >> n;
    	return 0;
    }
    
    

    心路历程

    QAQ
    

    Mother's Milk

    题意

    三个杯子的容量为a,b,c,每次选一个杯子X倒到另一个杯子Y里,直到Y倒不下或X倒空。问杯子c在杯子a为空的情况下水体积的所有可能的取值?


    题解

    状态只有20^3个,爆搜即可。
    dfs的具体写法就是写六个状态转移,用123的全排列可以简化代码。
    倒水的过程我封装了一下。


    代码

    int n;
    int m;
    int a, b, c;
    set<int> ans;
    bool pour(int& x, int& y,int aa,int bb) {
    	if (x==0||y == bb)return 0;
    	if (x + y <= bb)y = x + y,x=0;
    	else x = x + y - bb, y = bb;
    	return 1;
    }
    void dfs(int x, int y, int z) {
    	if (ans.count(x * 10000 + y * 100 + z))return;
    
    	ans.insert(x * 10000 + y * 100 + z);
    	int tx = x, ty = y, tz = z;
    	if (pour(x, y, a, b))dfs(x, y, z); x = tx, y = ty;
    	if (pour(y, x, b, a))dfs(x, y, z); x = tx, y = ty;
    	if (pour(x, z, a, c))dfs(x, y, z); x = tx, z = tz;
    	if (pour(z, x, c, a))dfs(x, y, z); x = tx, z = tz;
    	if (pour(y, z, b, c))dfs(x, y, z); y = ty, z = tz;
    	if (pour(z, y, c, b))dfs(x, y, z); y = ty, z = tz;
    }
    int main() {
    	FAST_IO;
    	
    	cin >>a>>b>>c;
    	int i = 1;
    	int last = -1;
    	dfs(0, 0, c);
    		set<int> out;
    		for (auto t : ans)if(t/10000==0)out.insert(t%100);
    		for (auto t : out)cout << t << ' ';
    		cout << endl;
    	cin >> n;
    }
    
    
    
    

    心路历程

    一开始以为有什么技巧,想着用迭代加深来判dfs结束条件,结果想歪了。  
    其实所有状态搜完,dfs就结束了。
    
    

    Prime Palindromes

    题意

    问区间(a,b)有哪些质数是回文数。


    题解

    判断一个1e8的质数,直接暴力即可。
    如何生成回文数?我用了一个数组,用dfs生成前一半,然后在dfs底层对称一下,算出它对应的数。
    数组可以用string代替,这样就可以reverse生成对称串了(其实数组也可以用reverse,不过string可以拼接)。
    还有直接生成数字的递归写法。


    代码

    #include<algorithm>
    #include<iostream>
    #include<sstream>
    #include<stdlib.h>
    #include<string.h>
    #include<assert.h>
    #include<math.h>
    #include<stdio.h>
    #include<vector>
    #include<queue>
    #include<string>
    #include<ctime>
    #include<stack>
    #include<map>
    #include<set>
    #include<list>
    using namespace std;
    #define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
    #define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
    #define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
    #define debug(x) cerr<<#x<<" = "<<(x)<<endl
    #define mmm(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    #define MD(x) x%=mod
    #define FAST_IO ios_base::sync_with_stdio(false); cin.tie(nullptr)
    //#define pii pair<int,int>
    //#define x first
    //#define y second
    typedef double db;
    typedef long long ll;
    const int MAXN = 1e6;;
    const int maxn = 1e3 + 5;
    const int INF = 1e9;
    const db eps = 1e-7;
    const int mod = 1e9 + 7;
    int n;
    int N;
    //int ans;
    int num[10];
    int isp[10005];
    set<int> ans;
    int a, b;
    void sieveP() {
    	rep(i, 1, 10000) {
    		int ok = 1;
    		for (int j = 2; j*j <= i; j++) {
    			if (i%j == 0)ok = 0;
    		}
    		if (ok)isp[i] = 1;
    	}
    }
    bool isprime(int x) {
    	int ok = 1;
    	for (int i = 2; i*i <= x;i++)if (isp[i]) {
    		if (x%i == 0)ok = 0;
    	}
    	return ok;
    }
    void  gene(int n) {
    	if (n == 0) {
    		if (N % 2) { rep(i, 0, 9)  { num[N / 2 + 1] = i; gene(n - 1); } }
    		else {
    			rep(i, N / 2 + 1, N)num[i] = num[N + 1 - i];
    			int val = 0;
    			rep(i, 1, N)val*= 10, val += num[i];
    		//	cout << val << endl; 
    			if (val<=1e8&&isprime(val)&&val>=a&&val<=b)ans.insert(val);
    			return;
    		}
    	}
    	else if (n == -1) {
    		rep(i, N / 2 + 2, N)num[i] = num[N + 1 - i];
    		int val=0;
    		rep(i, 1, N)val *= 10, val += num[i];
    		//cout << val << endl;
    		if (isprime(val) && val >= a && val <= b)ans.insert(val);
    		return;
    	}
    	else rep(i, 0, 9) { num[n] = i; gene(n - 1); }
    }
    
    int main() {
    	FAST_IO;
    	sieveP();
    	 cin >> a >> b;
    	int bita = 0;
    	int bitb = 0,aa=a,bb=b;
    	while (aa) { bita++; aa /= 10; }
    	while (bb) { bitb++; bb /= 10; }
    	for (N = bita; N <= bitb; N++) {
    		gene(N / 2);
    	}
    	for (auto t : ans)cout << t << endl;
    	cin >> n;
    	return 0;
    }
    
    /*
    5 100000000
    */
    
    
    

    以下是三个标程:

    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    #include <stdlib.h>
    
    FILE *fout;
    long a, b;
    
    int
    isprime(long n)
    {
        long i;
    
        if(n == 2)
    	return 1;
    
        if(n%2 == 0)
    	return 0;
    
        for(i=3; i*i <= n; i+=2)
    	if(n%i == 0)
    	    return 0;
    
        return 1;
    }
    
    void
    gen(int i, int isodd)
    {
        char buf[30];
        char *p, *q;
        long n;
    
        sprintf(buf, "%d", i);
    
        p = buf+strlen(buf);
        q = p - isodd;
    
        while(q > buf)
    	*p++ = *--q;
        *p = '';
    
        n = atol(buf);
        if(a <= n && n <= b && isprime(n))
    	fprintf(fout, "%ld
    ", n);
    }
    
    void
    genoddeven(int lo, int hi)
    {
        int i;
    
        for(i=lo; i<=hi; i++)
            gen(i, 1);
    
        for(i=lo; i<=hi; i++)
            gen(i, 0);
    }
    
    void
    generate(void)
    {
        genoddeven(1, 9);
        genoddeven(10, 99);
        genoddeven(100, 999);
        genoddeven(1000, 9999);
    }
    
    void
    main(void)
    {
        FILE *fin;
    
        fin = fopen("pprime.in", "r");
        fout = fopen("pprime.out", "w");
        assert(fin != NULL && fout != NULL);
    
        fscanf(fin, "%ld %ld", &a, &b);
    
        generate();
        exit (0);
    }
    
    //注意到偶数回文串必被11整除,所以生成奇数的即可
    #include <iostream.h>
    #include <fstream.h>
    #include <stdlib.h>
    
    int primelist[100000];
    int nprimes;
    
    int isPrime(int num);
    int reverse2(int i, int j);
    
    int compare(const void *p, const void *q) { return *(int *)p-*(int *)q; }
    
    void main (void) {
        ifstream infile("pprime.in");
        ofstream outfile("pprime.out"); 
        int i, j, begin, end, num;
        infile>>begin>>end;
        if (begin <= 11 && 11 <=end)
            primelist[nprimes++] = 11;
        for (j = 0; j <= 999; j++)
            for (i = 0; i <= 9; i++)  {
    	    num = reverse2(j,i);
    	    if (num >= begin && num <=end && isPrime(num)) 
      	        primelist[nprimes++] = num;
            }
        qsort(primelist, nprimes, sizeof(int), compare);
        for (i = 0; i < nprimes; i++)
    	outfile << primelist[i] << "
    ";
    }
    
    int
    reverse2(int num, int middle) {
        int i, save=num, digit, combino = 1;
        for (i = 0; num; num /= 10) {
    	digit = num % 10;
    	i = 10 * i + digit;
    	combino *= 10;
        }
        return i+10*combino*save+combino*middle;
    }
    	
    int isPrime(int num) {
        int i;
        if (num <= 3) return 1;
        if (num%2 == 0 || num%3 ==0) return 0;
        for (i = 5; i*i <= num; i++)
    	if (num %i ==0)
    	    return 0;
        return 1;
    }
    
    //递归不用数组
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    
    FILE *f;
    int a, b;
    
    int isPrime(int num);
    void genPalind(int num, int add, int mulleft, int mulright);
    void tryPalind(int num);
    
    int main(){
      int i;
      char first;
      f=fopen("pprime.in", "r");
      fscanf(f, "%d%d", &a, &b);
      fclose(f);
      f=fopen("pprime.out", "w");
      if (a<=5)
        fprintf(f, "%i
    ", 5);
      if (a<=7 && b>=7)
        fprintf(f, "%i
    ", 7);
      if (a<=11 && b>=11)
        fprintf(f, "%i
    ", 11);
      genPalind(3, 0, 100, 1);
      genPalind(5, 0, 10000, 1);
      genPalind(7, 0, 1000000, 1);
      fclose(f);
    }
    
    void tryPalind(int num){
      if (!(num&1))
        return;
      if (num<a || num>b)
        return;
      if (!(num%3) || !(num%5) || !(num%7))
        return;
      if (!isPrime(num))
        return;
      fprintf(f, "%d
    ", num);
    }
    
    void genPalind(int num, int add, int mulleft, int mulright){
      int i, nmulleft, nmulright;
      if (num==2){
        for (i=0; i<10; i++)
          tryPalind(add+mulleft*i+mulright*i);
      }
      else if (num==1){
        for (i=0; i<10; i++)
          tryPalind(add+mulright*i);
      }
      else {
        nmulleft=mulleft/10;
        nmulright=mulright*10;
        num-=2;
        for (i=0; i<10; i++)
          genPalind(num, add+i*mulleft+i*mulright, nmulleft, nmulright);
      }
    }
    
    int isPrime(int num){
      int koren, i;
      koren=(int)sqrt(1.0*num);
      for (i=11; i<=koren; i+=2)
        if (!(num%i))
          return 0;
      return 1;
    }
    

    心路历程

    一开始打算写最后的那个标程,不会啊QAQ orz%%%
    
    

    Superprime Rib

    题意

    输出所有n位的super prime.
    super prime: 如果质数X,有X/10,X/100,X/1000...都是质数,那么它就是sprime


    题解

    上一题简化版,直接从第一个数字不断往后dfs,每层都是质数,所以剪枝性很强。


    代码

    //头文件省略
    
    int n;
    int N;
    //int ans;
    int num[10];
    int isp[10005];
    set<int> ans;
    int a, b;
    void sieveP() {
    	rep(i, 1, 10000) {
    		int ok = 1;
    		for (int j = 2; j*j <= i; j++) {
    			if (i%j == 0)ok = 0;
    		}
    		if (ok)isp[i] = 1;
    	}
    }
    bool isprime(int x) {
        if(x==1)return 0;
    	int ok = 1;
    	for (int i = 2; i*i <= x;i++)if (isp[i]) {
    		if (x%i == 0)ok = 0;
    	}
    	return ok;
    }
    void  gene(int n,int num) {
    	if (n == 0) { if(num/N)cout << num<<endl; return; }
    	rep(i, 0, 9) {
    		if (isprime(num * 10 + i))gene(n - 1, num * 10 + i);
    	}
    }
    
    int smain() {
    	FAST_IO;
    	sieveP();
    	cin >> n;
    	N = pow(10, n - 1);
    	gene(n,0);
    	cin >> n;
    	return 0;
    }
    

    心路历程


    成功的路并不拥挤,因为大部分人都在颓(笑)
  • 相关阅读:
    Assembly Manifest 通俗简易手册
    CruiseControl服务器安装配置
    关于URL编码
    从A到Z来说说Web开发
    通过注册表查看 .NET Framework的版本信息
    云数据存在哪里?
    C#中你可能不知道的8件事(zz)
    用PBKDF2 或BCrypt 来存储密码
    C++编译器什么时候为我们自动生成拷贝构造函数?
    C#中你可能不知道的8件事(zz)
  • 原文地址:https://www.cnblogs.com/SuuT/p/10530943.html
Copyright © 2011-2022 走看看