2023西工大NOJ (C语言版) 持续更新ing
目录
前言
代码均可AC,易错总结参见我的博客 NOJ(C)易错总结 (annesede.github.io)。
部分题目由于过于简单一次性AC,未能考虑可读性(其实是懒得改)。
题目分类如下,请按题目名称查找:
- 入门题:只涉及基本的输入输出
- 简单题:不涉及算法但有较多易错点
- 中等题:涉及简单的算法或数学知识
- 难题:涉及复杂的算法或数学知识
入门题
Hello World
#include<stdio.h>
int main(){
printf("Hello World");
return 0;
}
A+B
#include<stdio.h>
int main(){
int a = 0, b = 0;
scanf("%d %d",&a,&b);
printf("%d",a+b);
return 0;
}
数据类型大小及范围
#include <stdio.h>
#include <limits.h>
int main(){
int id = 0;
scanf("%d",&id);
switch (id) {
case 1: // char
printf("%llu,%d,%dn",sizeof(char),CHAR_MIN,CHAR_MAX);
break;
case 2: // unsigned char
printf("%llu,%u,%un",sizeof(unsigned char),0,UCHAR_MAX);
break;
case 3: // short
printf("%llu,%hd,%hdn",sizeof(short),SHRT_MIN,SHRT_MAX);
break;
case 4: // unsigned short
printf("%llu,%hu,%hun",sizeof(unsigned short),0,USHRT_MAX);
break;
case 5: // int
printf("%llu,%d,%dn",sizeof(int),INT_MIN,INT_MAX);
break;
case 6: // unsigned int
printf("%llu,%u,%un",sizeof(unsigned int),0,UINT_MAX);
break;
case 7: //long
printf("%llu,%ld,%ldn",sizeof(long),LONG_MIN,LONG_MAX);
break;
case 8: // unsigned long
printf("%llu,%u,%lun",sizeof(unsigned long),0,ULONG_MAX);
break;
case 9: // long long
printf("%llu,%lld,%lldn",sizeof(long long),LLONG_MIN,LLONG_MAX);
break;
case 10: // unsigned long long
printf("%llu,%u,%llun",sizeof(unsigned long long),0,ULLONG_MAX);
break;
}
return 0;
}
平均值
#include <stdio.h>
int main(){
int a = 0, b = 0;
scanf("%d %d",&a,&b);
int c = ((b-a)>>1)+a;
printf("%d",c);
return 0;
}
进制转换
#include <stdio.h>
int main(){
unsigned int a = 0;
scanf("%d",&a);
printf("%X,%o",a,a);
return 0;
}
浮点数输出
#include <stdio.h>
int main(){
double a = 0.0f;
scanf("%lf",&a);
printf("%.6lf,%.2lf,%.8lf",a,a,a);
return 0;
}
动态宽度输出
#include <stdio.h>
int main(){
int n = 0, m = 0, k = 0;
scanf("%d %d",&n,&m);
int tmp = n;
while (tmp) {
tmp /= 10;
++k;
}
for (int i = 0; i < m-k; ++i) {
printf("%d",0);
}
printf("%d",n);
return 0;
}
计算地球上两点之间的距离
#include <stdio.h>
#include <math.h>
#define RADIUS 6371.000000
#define PI 3.1415926
int main(){
double phi1, phi2, lambda1, lambda2, distance;
scanf("%lf %lf",&phi1,&lambda1);
scanf("%lf %lf",&phi2,&lambda2);
phi1 = phi1*PI/180;
phi2 = phi2*PI/180;
lambda1 = lambda1*PI/180;
lambda2 = lambda2*PI/180;
double havRatio = (1-cos(phi2-phi1))/2+cos(phi1)*cos(phi2)*(1-cos(lambda2-lambda1))/2;
distance = asin(sqrt(havRatio))*2*RADIUS;
printf("%.4lfkm",distance);
return 0;
}
风寒指数
#include <stdio.h>
#include <math.h>
int main(){
double v,T;
scanf("%lf %lf",&v,&T);
int chill = 13.12f+0.6215f*T-11.37f*pow(v,0.16f)+0.3965f*T*pow(v,0.16f)+0.5f;
printf("%d",chill);
return 0;
}
乘数模
#include <stdio.h>
int main(){
long long a,b,m,r;
scanf("%lld %lld %lld",&a,&b,&m);
r = ((a%m)*(b%m))%m;
printf("%lld",r);
return 0;
}
组合数
#include<stdio.h>
int main(){
int cnt = 0, n, m;
scanf("%d",&n);
for(int a = 0; a <= 9; ++a){
for(int b = 0; b <= 9; ++b){
for(int c = 0; c <= 9; ++c){
for(int d = 0; d <= 9; ++d){
m = a+b+c+d;
if (m == n){
++cnt;
}
}
}
}
}
printf("%d",cnt);
return 0;
}
余数和
#include <stdio.h>
int main() {
unsigned int sum = 0, n, k;
scanf("%u %u",&n,&k);
for (unsigned int i = 1; i <= n; ++i) {
sum += k%i;
}
printf("%u",sum);
return 0;
}
佩尔数
#include <stdio.h>
int PA(int n){
if (n == 0) return 0;
else if (n == 1) return 1;
return 2*PA(n-1)+PA(n-2);
}
int PB(int n){
int p0 = 0, p1 = 1, pn;
for (int i = 0; i <= n; ++i) {
if (i == 0) pn = p0;
else if (i == 1) pn = p1;
else {
pn = 2 * p1 + p0;
p0 = p1;
p1 = pn;
}
}
return pn;
}
int main() {
int n, p;
scanf("%d",&n);
if (n&1) p = PA(n);
else p = PB(n);
printf("%d",p);
return 0;
}
可变参数累加
#include <stdio.h>
#include <stdarg.h>
int sum(int start,...){
va_list vaList;
int sum = 0;
va_start(vaList,start);
while (start){
sum += start;
start = va_arg(vaList,int);
}
va_end(vaList);
return sum;
}
int main() {
int a,b,c,d,e,f;
scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&e,&f);
int sumMinus = sum(a,b,0) - sum(c,d,e,f,0);
printf("%d",sumMinus);
return 0;
}
可变参数平均
#include <stdio.h>
#include <stdarg.h>
double avg(int num,...){
va_list vaList;
double sum = 0.0f;
va_start(vaList,num);
for (int i = 0; i < num; ++i) {
sum += va_arg(vaList,int);
}
va_end(vaList);
return sum/num;
}
int main() {
int a,b,c,d,e;
scanf("%d %d %d %d %d",&a,&b,&c,&d,&e);
double avgMinus = avg(2,a,b) - avg(3,c,d,e);
printf("%.4f",avgMinus);
return 0;
}
简单题
颜色模型转换
#include <stdio.h>
#include <stdio.h>
#include <math.h>
double findmax(double a, double b, double c) {
return a >= b ? (a >= c ? a : c) : (b >= c ? b : c);
}
double findmin(double a, double b, double c) {
return a <= b ? (a <= c ? a : c) : (b <= c ? b : c);
}
int main()
{
int R, G, B;
double r, g, b;
double max, min;
double H, S, V;
scanf("%d %d %d",&R,&G,&B);
r = (double)((R > 0 ? R : 0) / 255.0f);
g = (double)((G > 0 ? G : 0) / 255.0f);
b = (double)((B > 0 ? B : 0) / 255.0f);
max = findmax(r, g, b);
min = findmin(r, g, b);
V = max;
if (max < 1e-9) {
S = 0.0f;
}
else {
S = (max - min) / max;
}
if (max - min < 1e-9) {
H = 0.0f;
}
else {
if (max == r) {
H = 60.0f * (g - b) / (max - min);
}
else if (max == g) {
H = 60.0f * (2.0f + (b - r) / (max - min));
}
else if (max == b) {
H = 60.0f * (4.0f + (r - g) / (max - min));
}
else {
return -1;
}
if (H < 1e-9) {
H = H + 360.0f;
}
}
printf("%.4lf,%.4lf%%,%.4lf%%", H, S * 100, V * 100);
return 0;
}
方阵
#include <stdio.h>
int main(){
int n,m;
scanf("%d",&n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
m = (i-j) > 0 ? (i-j) : (j-i);
printf("%d ",m);
}
printf("n");
}
return 0;
}
分数的加、减、乘、除
#include <stdio.h>
int gcd(int a,int b) {
if (b == 0) return a;
else return gcd(b,a%b);
}
int main() {
int a,b,c,d;
scanf("%d",&a);
getchar();
scanf("%d",&b);
getchar();
scanf("%d",&c);
getchar();
scanf("%d",&d);
printf("(%d/%d)+(%d/%d)=%d/%dn",a,b,c,d,(a*d+b*c)/gcd(a*d+b*c,b*d),b*d/gcd(a*d+b*c,b*d));
printf("(%d/%d)-(%d/%d)=%d/%dn",a,b,c,d,(a*d-b*c)/gcd(a*d-b*c,b*d),b*d/gcd(a*d-b*c,b*d));
printf("(%d/%d)*(%d/%d)=%d/%dn",a,b,c,d,(a*c)/gcd(a*c,b*d),b*d/gcd(a*c,b*d));
printf("(%d/%d)/(%d/%d)=%d/%dn",a,b,c,d,(a*d)/gcd(a*d,b*c),b*c/gcd(a*d,b*c));
return 0;
}
操作数
#include <stdio.h>
int sumDig(int n){
int sum = 0;
while(n){
sum += n%10;
n /= 10;
}
return sum;
}
int main(){
int n,cnt=0;
scanf("%d",&n);
while(n){
n -= sumDig(n);
++cnt;
}
printf("%d",cnt);
return 0;
}
比率
#include <stdio.h>
#include <math.h>
int gcd(int a,int b){
if (b == 0) return a;
else return gcd(b,a%b);
}
int cntDig(double x){
int cnt = 0;
while(x != floor(x)){
++cnt;
x *= 10;
}
return cnt;
}
int main(){
double x;
scanf("%lf",&x);
int cnt = cntDig(x), n, m, g;
m = pow(10,cnt);
n = (int)(x*m);
g = gcd(m,n);
m /= g;
n /= g;
printf("%d/%d",n,m);
return 0;
}
级数和
#include <stdio.h>
#include <math.h>
double decimal (int n){
double m = (double)n+1;
while(floor(m)){
m /= 10;
}
return m+n;
}
int main(){
int n;
scanf("%d",&n);
double sum = 0.0f, term;
for (int i = 1; i < n; ++i) {
term = decimal(i);
sum += term;
printf("%g+",term);
}
term = decimal(n);
sum += term;
printf("%g=%g",term,sum);
return 0;
}
对称数
#include <stdio.h>
int main(){
int n;
scanf("%d",&n);
int a = (n/100)%10;
int b = (n/10)%10;
int c = n%10;
if ((b == 0 || b == 1 || b == 8) && ((a == 6 && c == 9) || (a == 9 && c == 6)
|| ((a == 0 || a == 1 || a == 8) && (c == 0 || c == 1 || c == 8)))){
printf("Yesn");
} else {
printf("Non");
}
return 0;
}
倍数和
#include <stdio.h>
int main(){
unsigned int t = 0;
scanf("%u", &t);
unsigned int arrn[t];
for(unsigned int i = 0; i < t; i++){
scanf("%u", &arrn[i]);
}
for(unsigned int j = 0; j < t; j++){
unsigned int res = 0;
for(unsigned int x = 1; x < arrn[j]; x++){
if(x % 3 == 0 || x % 5 == 0){
res += x;
}
}
printf("%un", res);
}
return 0;
}
最大数字
#include <stdio.h>
#include <stdbool.h>
bool isNonDecr(unsigned int n){
unsigned int left;
while(n){
left = (n/10)%10;
if (left > (n%10)){
return false;
}
n /= 10;
}
return true;
}
int main() {
unsigned int n, res;
scanf("%u",&n);
while(!isNonDecr(n)){
--n;
}
printf("%u",n);
return 0;
}
毕达哥拉斯三元组
#include <stdio.h>
unsigned long long pythagoras(unsigned int sum){
// a as short catheti, b as long catheti, c as hypotenuse
unsigned int a,b,c;
for (a = 1; a <= sum/4; ++a){
for (b = a+1; b <= sum/2; ++b){
c = sum-a-b;
if ((a+b > c) && (a*a+b*b == c*c)){
return a*b*c;
}
}
}
}
int main(){
unsigned int n;
scanf("%u",&n);
printf("%llu", pythagoras(n));
return 0;
}
竖式乘法
#include <stdio.h>
#include <math.h>
typedef unsigned int uint;
uint digit(uint x){
uint cnt = 0;
if (x == 0){
return 1;
}
while(x){
x /= 10;
++cnt;
}
return cnt;
}
uint getDigital(uint x, uint n){
x /= (uint)pow(10,n-1);
return x%10;
}
int main(){
uint up, down;
scanf("%u %u",&up,&down);
uint ans = up*down, len = digit(ans)+1, downLen = digit(down);
for (uint i = 0; i < len-digit(up); ++i) {
printf(" ");
}
printf("%un",up);
printf("x");
for (uint i = 1; i <= len-downLen-1; ++i) {
printf(" ");
}
printf("%un",down);
for (uint i = 1; i <= len; ++i) {
printf("-");
}
printf("n");
uint tmp;
for (uint i = 1; i <= downLen; ++i) {
tmp = getDigital(down,i)*up;
if (i == downLen){
printf("+");
} else {
for (uint j = 1; j <= len-digit(tmp)-i+1; ++j) {
printf(" ");
}
}
printf("%un",tmp);
}
for (uint i = 1; i <= len; ++i) {
printf("-");
}
printf("n");
printf(" %u",ans);
return 0;
}
查找数列
#include <stdio.h>
int main(){
int cnt = 1, sum = 0, n, res;
scanf("%d",&n);
while(n-sum > 0){
sum += cnt;
++cnt;
}
sum -= cnt;
res = n-sum == 0 ? cnt : (n-sum-1);
printf("%d",res);
return 0;
}
俄罗斯农夫乘法
#include <stdio.h>
int main(){
int multi = 0, a, b;
scanf("%d %d",&a,&b);
while(a){
printf("%d %dn",a,b);
if (a&1) {
multi += b;
}
a >>= 1;
b <<= 1;
}
printf("%d",multi);
return 0;
}
哈沙德数
#include <stdio.h>
int HarshadNumber(int n){
int t = n, s = 0;
while (t) {
s += t%10;
t /= 10;
}
if ((s == 0) || (n%s != 0)) return 0;
if (s == 1) return 1;
return n/s;
}
int main(){
int cnt = 0, n;
scanf("%d",&n);
if (n == 1) cnt = 1;
while ((n != 0) && (n != 1)) {
n = HarshadNumber(n);
if (n) ++cnt;
}
printf("%d",cnt);
return 0;
}
基思数
#include <stdio.h>
int arr[8] = {0};
int init(int n){
int cnt = 0;
while (n) {
arr[cnt++] = n%10;
n /= 10;
}
return cnt;
}
void isKeith(int n, int len){
int i = len - 1;
while (arr[i] < n){
int sum = 0;
for (int j = 0; j < len; ++j) {
sum += arr[(i-j+len)%len];
}
arr[i] = sum;
i = (i-1+len)%len;
}
if (arr[i] == n) printf("Yes");
else printf("No");
}
int main() {
int n;
scanf("%d",&n);
isKeith(n,init(n));
return 0;
}
二进制表示
#include <stdio.h>
#include <stdbool.h>
void binary(int a){
bool flag = false;
for (int i = 15; i >= 0 ; --i) {
if ((a>>i)&1) {
if (flag) printf("+");
if (i >= 2){
printf("2(");
binary(i);
printf(")");
}
if (i == 1) printf("2");
if (i == 0) printf("2(0)");
flag = true;
}
}
}
int main() {
int a;
scanf("%d",&a);
binary(a);
return 0;
}
冰雹数列
#include <stdio.h>
int main() {
int n;
scanf("%d",&n);
while (n != 1) {
printf("%d ",n);
if (n&1) n = 3 * n + 1;
else n /= 2;
}
printf("1");
return 0;
}
中等题
幂数模
#include <stdio.h>
typedef unsigned long long uint64;
uint64 fastPowerMod (uint64 t, uint64 e, uint64 m){
uint64 r = 1;
while (e){
if (e&1){
r = (r*t)%m;
}
t = (t*t)%m;
e >>= 1;
}
return r;
}
int main(){
uint64 a,b,m,r;
scanf("%llu %llu %llu",&a,&b,&m);
r = fastPowerMod(a,b,m);
printf("%llu",r);
return 0;
}
倒水
#include <stdio.h>
#include <string.h>
#define INF 0x3f3f3f3f
const int maxSize = 10000;
int distTable[10000][10000];
int queue[10000][2] = {0};
int bfs(int n, int m, int d){
int head = 0, tail = 1;
memset(distTable, 0x3f, sizeof(distTable));
distTable[0][0] = 0;
while(tail != head){
int a = queue[head][0], b = queue[head][1];
if (a == d || b == d) {
return distTable[a][b];
}
head = (head+1)%maxSize;
// full
if(distTable[a][m] == INF) {
distTable[a][m] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = a;
queue[tail][1] = m;
}
if(distTable[n][b] == INF) {
distTable[n][b] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = n;
queue[tail][1] = b;
}
// empty
if(distTable[a][0] == INF) {
distTable[a][0] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = a;
queue[tail][1] = 0;
}
if(distTable[0][b] == INF) {
distTable[0][b] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = 0;
queue[tail][1] = b;
}
// pour
if(a+b < n && distTable[a+b][0] == INF){
distTable[a+b][0] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = a+b;
queue[tail][1] = 0;
}
if(a+b >= n && distTable[n][a+b-n] == INF){
distTable[n][a+b-n] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = n;
queue[tail][1] = a+b-n;
}
if(a+b < m && distTable[0][a+b] == INF){
distTable[0][a+b] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = 0;
queue[tail][1] = a+b;
}
if(a+b >= m && distTable[a+b-m][m] == INF){
distTable[a+b-m][m] = distTable[a][b]+1;
tail = (tail+1)%maxSize;
queue[tail][0] = a+b-m;
queue[tail][1] = m;
}
}
return -1;
}
int main(){
int n,m,d;
scanf("%d %d %d",&n,&m,&d);
printf("%d", bfs(n,m,d));
return 0;
}
好数字
#include <stdio.h>
typedef unsigned long long uint64;
const uint64 mod = 1e9+7;
uint64 power(uint64 a, uint64 e){
uint64 r = 1;
while (e){
if (e&1){
r = (r*a)%mod;
}
a = (a*a)%mod;
e >>= 1;
}
return r;
}
int main(){
uint64 n, num;
scanf("%llu",&n);
num = power(4,n/2)*power(5,n-n/2)%mod;
printf("%llu",num);
return 0;
}
阶乘倍数
#include <stdio.h>
#include <stdbool.h>
typedef unsigned long long uint64;
uint64 primeFactNum = 0;
uint64 prime[20] = {0}, num[20] = {0};
bool isMulti(uint64 n){
uint64 primeNum, tmp;
for (uint64 i = 1; i <= primeFactNum; ++i) {
primeNum = 0;
tmp = n;
while (tmp) {
primeNum += tmp/prime[i];
tmp /= prime[i];
}
if(primeNum < num[i]) {
return false;
}
}
return true;
}
void solveFact(uint64 k){
for (uint64 i = 2; i*i <= k; ++i) {
if(k%i == 0){
++primeFactNum;
prime[primeFactNum] = i;
while (k%i == 0){
++num[primeFactNum];
k /= i;
}
}
}
if (k > 1){
++primeFactNum;
prime[primeFactNum] = k;
++num[primeFactNum];
}
}
int main(){
uint64 left = 1, right = 1e19, mid, n, k;
scanf("%lld",&k);
solveFact(k);
while(left <= right){
mid = ((right-left)>>1)+left;
if (isMulti(mid)){
right = mid-1;
n = mid;
} else {
left = mid+1;
}
}
printf("%lld",n);
return 0;
}
方案数
#include <stdio.h>
int main(){
int cnt = 0, n;
scanf("%d",&n);
for (int i = 1; i*(i+1) <= 2*n; ++i) {
if ((n-i*(i-1)/2)%i == 0){
++cnt;
}
}
printf("%d",cnt);
return 0;
}
素数
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
typedef unsigned long long uint64;
uint64 primeNum(uint64 a, uint64 b){
bool isPrime[b+1];
memset(isPrime,1,b+1);
uint64 cnt = 0;
for (uint64 i = 2; i <= b; ++i){
if (isPrime[i]){
for (uint64 j = 2; j*i <= b; ++j){
isPrime[j*i] = false;
}
}
}
for (uint64 i = a; i <= b; ++i){
cnt += isPrime[i];
}
return cnt;
}
int main(){
uint64 a,b,num;
scanf("%llu %llu",&a,&b);
num = primeNum(a,b);
printf("%llu",num);
return 0;
}
光线追踪
#include <stdio.h>
unsigned int gcd(unsigned int a, unsigned int b){
if (b == 0) return a;
return gcd(b,a%b);
}
int main(){
unsigned int n,x,l;
scanf("%u %u",&n,&x);
l = 3*(n-gcd(n,x));
printf("%u",l);
return 0;
}
运动会
#include <stdio.h>
#include <stdbool.h>
int phiEuler(int n){
int phi[n+1],prime[n+1];
bool isSieved[n+1];
int sum = 0,cnt = 1, comp;
prime[0] = 1;
phi[1] = 1;
for (int i = 2; i < n; ++i){
if (!isSieved[i]){
prime[cnt++] = i;
phi[i] = i-1;
}
for (int j = 1; i*prime[j] <= n; ++j){
comp = i*prime[j];
isSieved[comp] = true;
if (i%prime[j] == 0){
phi[comp] = prime[j]*phi[i];
break;
} else{
phi[comp] = (prime[j]-1)*phi[i];
}
}
}
for (int i = 1; i <= n-1; ++i) {
sum += phi[i];
}
return sum;
}
int main() {
int n, num;
scanf("%d",&n);
num = n == 1 ? 0 : (2*phiEuler(n)+1);
printf("%d",num);
return 0;
}