数论

数论

关于约数

相亲数:

题目:https://www.luogu.com.cn/problem/P1851

数学中的相亲数,也就是说两个数中任意一个的所有因子(除本身外)之和等于另外一个数。

1.O(n sqrt(n))算法:考虑约数成对出现,注意完全平方数(该方法已经可以AC(76ms))。

int j;
for(register int i=1;i<=100000;i++)
{
    for(j=1;j*j<=i;j++)
    {
        if(i%j==0)
        {
            pr[i]+=j;
            pr[i]+=i/j;
        }
    }
    j--;
    if(j*j==i)pr[i]-=j;
    pr[i]-=i;
}

2.O(n log(log(n)))算法:筛法优化。(秒啊~~)

for(int i=1;i<=20000;i++)
    for(int j=i;i*j<=20000;j++)
        pr[i*j]+=i;

一定注意读题,比如这个题就:

1.(6≤S≤18000) ,找出序列号不小于 S。

  1. A 表示第一个序列号不小于 S 的有“非常好友”的同学,B 是 A 的“非常好友”,而不是:两者都得大于s.

更新:2020.11.12

试题 G:(2019国赛)
G:数正方形(难度:★★★★★

【问题描述】
在一个 N × N 的点阵上,取其中 4 个点恰好组成一个正方形的 4 个顶点,
一共有多少种不同的取法?
由于结果可能非常大,你只需要输出模 109 + 7 的余数。
在这里插入图片描述

如上图所示的正方形都是合法的。
【输入格式】
输入包含一个整数 N。
【输出格式】
输出一个整数代表答案。
【样例输入】
4
【样例输出】
20
【数据规模与约定】
对于所有评测用例,2 ≤ N ≤ 1000000。]()

import java.util.Scanner;

public class G {
   
   
	public static void main(String[] args) {
   
   
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		long ans=0;
		for(int i=1;i<=n;i++){
   
   
			ans+=(long)i*(long)i*(long)(n+1-i);
			ans%=1000000007;
		}
		System.out.println(ans);
	}
}

数论题目,我们枚举当边长固定的情况下,正方形的边均在最外层正方形的情况。
我们发现,当边长为x时,角在边的正方形的个数为x,如边长为4时有四种情况,
本质就是一个角在大正方形的一条边上来回移动。
在这里插入图片描述

所以我们推论当边长为x时,角在边的正方形的个数为x。
另一方面,
大的正方形可以分解成规规矩矩的小正方形,同样我们枚举顶点可以得到小正方形的个数,
同样,小正方形的个数也是有规律的。
1个4乘4的方格可以分成4个3乘3的方格
即2乘2个3乘3方格。

所以我们得出推论
ans[N]=Σ i * i * (n+1-i)
前面 i * i 表示最大边为(n+1-i)的大正方形的个数

试题 C: 切割

在这里插入图片描述

本题总分:10 分

【问题描述】

在 4 × 4 的方格矩阵中画一条直线。则直线穿过的方格集合有多少种不同的

可能?

这个里直线穿过一个方格当且仅当直线将该方格分割成面积都大于 0 的两

部分。

//以下代码未完善!!!!!!思路是这个

package no10Guosai;

import java.util.HashSet;
import java.util.Set;

class node{
	int x,y;

	public node(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	
}
public class C {
	static Set<String> set=new HashSet<>();
	static node[][] matrix=new node[17][4];
	public static void main(String[] args) {
		//初始化矩阵的四个点坐标
		init();
		for (int i = 1; i <=4; i++) {
			for (int j = 1; j <=4; j++) {
				
				matrix[(i-1)*4+j][0].x=(j-1);
				matrix[(i-1)*4+j][0].y=(i-1);
				matrix[(i-1)*4+j][1].x=(j-1+1);
				matrix[(i-1)*4+j][1].y=(i-1);
				matrix[(i-1)*4+j][2].x=(j);
				matrix[(i-1)*4+j][2].y=(i);
				matrix[(i-1)*4+j][3].x=(j-1);
				matrix[(i-1)*4+j][3].y=(i-1+1);
			}
		}
		work();//依次遍历,依据两点坐标建立二元一次直线方程
		System.out.println(set.size());
	}
	static void init() {
		for (int i = 1; i <=16; i++) {
			for (int j = 0; j <4; j++) {
				matrix[i][j]=new node(0, 0);
			}
			
		}
	}
	static void work() {
		for (int i = 1; i <= 16; i++) {
			for (int j = 0; j < 4; j++) {
				int x1=matrix[i][j].x;
				int y1=matrix[i][j].y;
				int x2 = 0,y2 = 0;
				System.out.println("当前--块"+i+"的第:"+j+"个节点");
				for (int k = i; k <=16; k++) {
					for (int l = 0; l < 4; l++) {
						x2=matrix[k][l].x;
						y2=matrix[k][l].y;
						//建立方程
						if((x2-x1!=0)&&(y2-y1!=0)){
							int kk=(y2-y1)/(x2-x1);
							int b=y1-kk*x1;
							if(kk!=0){
								System.out.println("    与块"+k+"的第:"+l+"个节点对比");
								check(kk,b);//检查直线穿过的方框
							}
								
								
						}
					}
					
				}
				
				
			}	
		}
	}
	private static void check(int k, int b) {
//		System.out.println("k="+k+" "+"b="+b);
		String s="";
		for (int i = 1; i <=16 ; i++) {//对每个格子
			int y_0=k*matrix[i][0].x+b;
			int x_0=(matrix[i][0].y-b)/k;
			int y_1=k*matrix[i][1].x+b;
			int x_3=(matrix[i][3].y-b)/k;
			if((y_0>matrix[i][0].y&&y_0<matrix[i][3].y)||
					(y_1>matrix[i][1].y&&y_1<matrix[i][2].y)||
						(x_0>matrix[i][0].x&&x_0<matrix[i][1].x)||
							(x_3>matrix[i][3].x&&x_3<matrix[i][2].x)||
								(matrix[i][0].x==x_0&&matrix[i][0].y==y_0&&matrix[i][2].y==y_1&&matrix[i][2].x==x_3)||
									(matrix[i][3].x==x_3&&matrix[i][1].y==y_1&&matrix[i][3].y==y_0&&matrix[i][1].y==y_1)
					){
				s+=i;
				set.add(s);
			}
			
		}
		
	}
}

trix[i][0].yy_0&&matrix[i][2].yy_1&&matrix[i][2].xx_3)||
(matrix[i][3].x
x_3&&matrix[i][1].yy_1&&matrix[i][3].yy_0&&matrix[i][1].y==y_1)
){
s+=i;
set.add(s);
}

	}
	
}

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值