• ベストアンサー

2 ~ 200 の素数 a, b, c (a < b < c) が、b - a = c - b を満たすa,b,cをビット操作を用いて求め、すべてを表示せよ

ちょっと考えてみました。でも、分かりません・・・まず、int型のintvalに200bitを割り当てて、intval=0としたいのですが、どうしたらいいのでしょう?? とりあえず考えてみたプログラムを誰か見て下さい!!お願いします。 #define BYTESIZE 200 #define MAX 200 main() { int i,j,intval=0; for(i=2;i<=MAX/2;i++) { if(intval&(1<<(i-1)){} else for(j=i*2;j<=MAX;j+=i)intval|=(1<<(j-1)); }/*素数を0、それ以外を1に for(i=2;i<=MAX/2;i++) for(j=2;j<=(MAX-i)/2;j++) if((intval&(1<<(i-1))&&(intval&(i+j-1))&&(intval&(1<<(i+2*j-1)))) print("%3d %3d %3d (%3d)\n",i,i+j,i+2*j,j); }/*三つ子の素数を調べ出力

質問者が選んだベストアンサー

  • ベストアンサー
  • nagata
  • ベストアンサー率33% (10/30)
回答No.1

まずint型は200ビットもありません。通常は32ビットです。 200ビット使いたければint型を7個用意する必要があります。 つまり int intval[7]; 宣言して、 intval[0] 0~31ビット intval[1] 32~63ビット intval[2] 64~95ビット . . . intval[6] 182~200ビット として使います。 第iビットの情報を取り出すときは (intval[i>>5]>>(i&31))&1 第iビットを1にするときは intval[i>>5]|=1<<(i&31); とすれば良いでしょう。 関数やマクロを用意することをお勧めします。 例えば int get(int intval[],int i) { return (intval[i>>5]>>(i&31))&1;/*0か1が返って来る。*/ } void on(int intval[],int i) { intval[i>>5]|=1<<(i&31); } という感じです。

chikako-imagawa
質問者

お礼

ありがとうございました!!無事プログラム完成しました!! ホントCって難しい。。。。。。ですねぇ。

その他の回答 (1)

noname#7273
noname#7273
回答No.2

「ビット操作を用いて」というのは、 ・素数かどうかの判定で使う ・b-a=c-bよりc=2*b-aの計算に使う ・自然数i(2~200)が素数かどうかを第iビットが0か1かで表す 等々が考えられます。 第3の意味での利用とすると、 200ビットを連続した領域として確保するわけですが、 ビット演算の練習としては あまり適切な練習問題とは思えません。 もしそうだとすれば、 nagataさんのいうように、int型変数をいくつか並べて、 それを一つとみてビット演算できるように関数やマクロを作る ことになるでしょう。 しかし、アセンブラではないので、その手間を考えると、 ビットで考えるよりは、大きさ200の配列を考えるのが 通常ではないでしょうか。 上記の1番目、2番目での利用ではないのですね? そこで、ご質問とはずれますが、 やはり第3の意味での利用だとして、 この場合、「ビット演算」というよりは、 配列を使った「論理演算」の練習問題と読み替え、 次のようにするのが普通ではないかと思います。 前半で、エラトステネスのふるいを使って、 自然数p(2~200)が素数かどうかを、 配列inval[p]に0(素数でない)か1(素数である)として設定します。 後半は、配列要素inval[a],inval[b],inval[c]を呼び出して 各a,b,cが素数かどうかの判断をします。 #include<stdio.h> main() { int flag[201]; int inval[204]; int i,p,k,j,a,b,c; /* using sieve of Eratosthenes */ printf("%4d",2); inval[2]=1; j=1; for(i=0;i<=200;i++){ flag[i]=1; /* true */ inval[i]=0; /* false */ } for(i=0;i<=100;i++) if(flag[i]){ p=2*i+3; printf("%4d",p); inval[p]=1; /* true */ for(k=i+p;k<=100;k+=p) flag[k]=0; /* false */ j++; } printf("\nthe number of primes %d\n",j); /* using logical operation */ for(a=2;a<200;a++) for(b=a+1;b<199;b++){ c=b+b-a; if(inval[a]&&inval[b]&&inval[c]&&(c<=200)) printf("%d-%d-%d ",a,b,c); } } (あるいは、このプログラムの応用として、 自然数iが素数かどうかを、配列の第i要素の 第1ビット目が0か1かで表すという方法もあります。) 以上、勝手な読み替えをして申し訳ありません。 ご参考まで申し上げたくて投稿いたしました。

chikako-imagawa
質問者

お礼

ありがとうございます!!一応ヒントとして先生が普通に作ったプログラム(配列を使って素数でない項に1をいれていく)というプログラムがあって、それをbit演算を使ってやるって問題だったんです。とりあえず、プログラムは完成しました!!!

関連するQ&A

  • 【c++】2進数の表示が上手くいきません

    サブ関数を利用して、-15~15までの値を1刻みで10進数16進数8進数2進数を表示するプログラムを作っているのですが悩んでいます。 以下のようにやってるのですがデバッグが上手くいきません。 どこが悪いのでしょうか? #include<stdio.h> void sub(int a) { int i,wc; for(i=31;i>=0;i--) { wc=(a>>i)&0x01; if(i%4==3) printf(" "); printf("%1d",wc); } printf("\n"); return; } int main(void) { int wc,a,s,j,b; printf("10進数,16進数,8進数,2進数\n"); for(s=-15;s<=15;s++) { printf("%d %x %o \n",s,s,s); printf("%d\n",sub(a)); } return 0; } 初心者なのでありえない間違えがあるかと思います。 ご教授お願いしますm(_ _)m

  • 作っているプログラムが分かりません・・・

    プログラムが… 以下のプログラムを作っているのですが、よく分かりません・・・ A監督が 77,B走塁コーチは 78 です.さて,77 と 78の素因数の和は等しくなっています. つまり,77=7×11,78=2×3×13,7+11=18,2+3+13=18 となっています. このように,素因数の和が互いに等しいという条件を満たすような, 差が 1 の自然数の組を 20000 以下でできるだけ多く探索しましょう. ここで,20000 以下には 26 組しかないことがわかっています. #include<stdio.h> #difine MAX 20000 int main(){ int sum[MAX+1]; int i,j,n; for(i = 2;i <= MAX;i++){ j = 2; while(j*j <= i){ if(i % j == 0){ _________________; break; } else j++; } if(j*j > i) ___________________; } n = 0; for(i = 2;i < MAX;i++) if(sum[i] == sum[i+1]){ n++; printf("%3d (%d,%d)\n",n,i,i+1); } return 0; } 補足 分からないのはプログラムの書き方で _________________;の部分だけでも答えていただけるとありがたいです。

  • 【C→JAVA】素数の組の数を求めるプログラム

    以下はC言語のプログラムです。 標準入力に正の偶数値 n(2≦n≦10,000) を入力すると足して n になる素数の組の数を求め、 標準出力に出力するプログラムなのですが、 これをJAVA用のプログラムに置き換えるとすると どのようなプログラムになるのでしょうか? よろしくお願いいたします。 #include <stdio.h> #include <math.h> //Compiler version gcc 6.3.0 #define N 10000 int primes[N + 1] = {0}; void sieve(int); int main() { int n,count = 0; sieve(N); scanf("%d",&n); for (int i = 1;i <= n / 2 + 1;i++) { for (int j = i + 1;j < n;j++) { if (primes[i] && primes[j] && i + j == n) { count++; } } } printf("%d\n",count); return 0; } void sieve(int n) { int limit = (int)sqrt(n) + 1; for (int i = 2;i <= n;i++) { primes[i] = 1; } for (int i = 2;i < limit;i++) { if (primes[i]) { for (int j = 2; i * j <= n;j++) { primes[i * j] = 0; } } } }

  • 2つの自然数を入力しその間にある素数を表示する

    2つの自然数を入力して、その間にある素数を表示するプログラムです。 #include <stdio.h> main( ) { int a,b,c,i,j; printf("Input number 1:"); scanf("\n%d",&a); printf("Input number 2:"); scanf("\n%d",&b); if(a>b){ c=a; a=b; b=c; } for(i=a;a<b+1;i++){ for(j=2;j<i-1;j++){ if(i%j!=0){j++;} else{ if(i=j){ printf("\n%d",i); } } } } } i=aからbまで j=2からi-1まで iはjで 割り切れるか NO→(jを1つ増やす) YES→iはjと等しいか YES→iの値を表示 NO→(iを1つ増やす) END この部分がよくわかりませんfor文を使うんですか? ご指導お願いします。

  • プログラミングで二番目に大きい数を表示する

    指定された個数(100個以下)だけ整数を読み込んで,読み込んだ整数の一覧,それらのうちの最大値と二番目に大きい値とを表示するプログラムを作成。最大となる値が複数入力された場合も正しく処理する。 このプログラムで入力した数字が全部同じ時、二番目に大きい値はありません。と表示したいのですが、どのようにしたらいいのかわかりません。教えてください。あとこのプログラムで最大値と二番目に大きい値出せたのですが、念のため問題ないか確認お願いします。 #include <stdio.h> #define NUMBER 100 /*整数の個数の上限*/ int main(void) { int i; int num; int kazu[NUMBER]; int max; int sec; printf("整数は何個ですか:"); scanf("%d", &num); puts("整数を入力してください。"); for(i = 0; i<num; i++){ printf("%3d個目:",i+1); scanf("%d", &kazu[i]); } printf("入力された整数は%d個で、\n",num); for(i=0;i<num;i++) printf("%d ",kazu[i]); printf("です。\n"); sec = max = kazu[0]; for(i=1; i<num; i++){ if(kazu[i]>max) max=kazu[i]; } for(i=0;i<num;i++){ if(kazu[i]>max){ sec=max; max=kazu[i]; }else if((max>kazu[i]) && (kazu[i]>sec)) sec=kazu[i]; } printf("最大値は%dです。 \n",max); printf("二番目に大きい値は%dです。\n", sec); return(0); }

  • C言語のファイル操作についての質問です

    #include <stdio.h> #include<process.h> int main(void) { FILE *fp; int a[200], i, j, cnt, max, max_i; fp = fopen("data.txt", "r"); if (fp == NULL) { printf("file cannot open.\n"); exit(1); } for(i = 0; i < 200 && fscanf(fp, "%d", &a[i]) == 1; ++ i) ; fclose(fp); for(max = max_i = j = 0; j < i; ++ j){ int k; for(cnt = 0, k = j + 1; k < i; ++ k) cnt += (a[j] == a[k]); if(cnt > max) max = cnt; max_i = j; } printf("%d\n", a[max_i]); return 0; } これは「data.txt」というファイルから最頻値を探し出し、その値を表示するプログラムです。 しかし、このプログラムだと最頻値が1つしか表示できないので、 最頻値が複数ある場合でも、すべての最頻値の値を表示させるようなプログラムに書き換えてほしいです。 よろしくお願いします。 例)data.txt 30000 100 150 30000 30000 100 4320 100 出力↓ 30000 100

  • C言語を用いた45×45の逆行列の表示について・・・・。。

    次のプログラムを動かすと逆行列を求めることができます。 10×10の計算までは、スムーズに計算する事ができたのですが、 私が知りたい45×45の行列の計算になるとなぜかうまくいきません。 そこでみなさんにお聞きしたいのは、計算がうまくいかない理由がプログラムにあるのか、単にPCの限界なのか、それ以外なのか。みなさんからアドバイスをいただけないでしょうか? ※下のプログラム、見づらくてすいません。 #include <stdio.h> #define N 10 /* 元の数 */ #define N2 2*N /* プロトタイプ宣言 */ void Print(int k); /* 大域変数 */ double a[N][N2]= {/* 行列 Aおよび単位行列 */ { ここに45×45の正則行列&45×45の単位行列を入れます・・・。。 }; int main(void) { double d; int i,j,k; for (k=0;k<=N-1;k++) { Print(k); for(i=0;i<=N-1;i++) { if(i!=k) { d=a[i][k]/a[k][k]; for (j=k+1;j<=N2-1;j++) a[i][j]=a[i][j]-a[k][j]*d; a[i][k] = 0.0; } } d=a[k][k]; for (j=k;j<=N2-1;j++) a[k][j]=a[k][j]/d; } Print(N); } void Print(int k) { int i,j; printf("\n ステップ %d \n",k); /* 小見出し */ for(i=0;i<=N-1;i++) { /* 第i行を印刷 */ for(j=0;j<=N-1;j++) printf("%6.4f,",a[i][j]); printf(" : "); for(j=N;j<=N2-1;j++) printf("%6.4f,",a[i][j]); printf("\n"); } }

  • C言語の素数判定について質問です。

    C言語の素数判定について質問です。 「与えられた数値以下で、最大の素数を返す関数を作成しなさい。 素数が存在しない場合、0を返すこと。 int max_prime (int x);を使用する。」 という問題なのですが。まったくの初心者なので何をすればよいか分かりません。 例として以下のようなプログラムを見せられたのですが、他の例などないでしょうか。 もし分かるかたがいらっしゃれば教えていただけないでしょうか。よろしくお願いします。 #include<stdio.h> int is_prime (int i){ int a; for(a=2;a<=i-1;a++){ if(i%a == 0){ return i; } } return 0; } int max_prime(int x){ int i; for(i=x;i>1;i--){ if(is_prime(i)!=i){ return i; } } return 0; } int main(void){ int x,z; scanf("%d",&x); z=max_prime(x); printf("%d数値以下で最大の素数は[%d]である!\n",x,z); return 0; }

  • Cの素人がやってしまう・・・と言われた使い方

    関数set()を作って、下にコメントアウトされているプログラム と全く同じ動作をするプログラムを完成させよ。 main内部を変更してはならない。 関数set()内では鈎括弧を使用してはならない。 という問題で、終わるときにチェックされたのですが どうもsetでの中身が素人がよくやるやつ、といわれました。 int x[MAX]とやれ?ということなのでしょうか それともやはり&(*(x+i))の部分がおかしいということでしょうか? 確かにアドレスにアドレスを聞いているような理解としか、今は言いようがないのですが そいえば前回&*を使ってる人がいるけど・・・という話を聞きました 何かご指摘あればうれしいです 以下がコードになります。 #include <stdio.h> #define MAX 10 void set(int *x); int main() { int x[MAX]; int j; set(x); printf("KEKKA\n"); for (j = 0; j < MAX; ++j) { printf("%d\n", x[j]); } return 0; } void set(int *x) { int i; for(i = 0; i < MAX; ++i){ scanf("%d",&(*(x+i))); } } /* int main() { int x[MAX]; int j; for (j = 0; j < MAX; ++j) { scanf("%d", &x[j]); } printf("KEKKA\n"); for (j = 0; j < MAX; ++j) { printf("%d\n", x[j]); } return 0; } */

  • 迷路作成のプログラミング

    迷路作成のプログラミングをC++で作ったのですが、エラーが出ます。 どのように直せば良いか教えてください。 エラー内容は 'randoomize': 識別子が見つかりませんでした。 16 進型定数には、少なくとも 1 桁の 16 進数が必要です。 'kbhit': 識別子が見つかりませんでした 'getch': 識別子が見つかりませんでした です、、お願いします。 #include <stdio.h> #include <stdlib.h> #include <time.h> #define YOKO_MAX 200 #define ESC '\xlb' int n; int map[YOKO_MAX],count[YOKO_MAX]; int rr() { return rand() % 10>3; } void tate() { int i,j,k; printf("■"); for (i=0; i<n-1;i++) if(map[i]!=map[i+1] && rr()) { k=map[i+1]; count[k]=0; for(j=0; j<n; j++) if(map[j]==k) { map[j]=map[i]; count[map[i]]++; } printf(" "); } else printf("■"); printf("■\n"); } void last_tate() { int i,j,k; printf("■"); for (i=0; i<n-1;i++) { if(map[i]==map[i+1]) printf("■"); else { k=map[i+1]; for (j=0; j<n; j++) if (map[j]==k) map[j]=map[i]; printf(" ",map[i]); } } printf("■\n"); } void yoko() { int i,j; for (i=0; i<n; i++) if (count[i]>1 && rr()) { printf("■■"); for(i=0; i<n; i++) { if (count[j]==0) { count[j]=1; count[map[i]]--; map[i]=j;break; } } } else { printf("■"); } printf("■\n"); } void enter() { int i,k; k=rand() % n; for (i=0; i<n; i++) if(i==k) { printf("■"); } else { printf("■■"); } printf("■\n"); } void initialize() { int i; for (i=0; i<n; i++) { map[i]=i; count[i]=1; } randoomize(); } int main() { printf("無限に大きな迷路\n"); do { printf("\n迷路の横幅(2~200)?"); scanf("%d",&n); } while (n<2||n>=YOKO_MAX); printf("\n ESCキーを押すと止まる。\n"); initialize(); enter(); do { tate(); yoko(); } while (!kbhit()||getch()!=ESC); last_tate(); enter(); }