一些神奇的结论题

洛谷P2508 [HAOI2008]圆上的整点


题目描述

求一个给定的圆\((x^2+y^2=r^2)\),在圆周上有多少个点的坐标是整数。

输入输出格式

输入格式:

\(r\)

输出格式:

整点个数

解题思路

哔哩哔哩
看完这个视频后,问题转化成分解质因数,只不过将视频中的\(\sqrt{R}\)变成了\(R\)而已。则高斯素数的无论多少次方都毫无影响,\(4n+3\)型素数的影响由于幂次的翻倍而变成\(2*cnt+1\)

AC代码

#include<stdio.h>
#include<math.h>
int main(){
    int i,n,cnt=0,ans=1;
    scanf("%d",&n);
    for(i=2;i*i<=n;i++,cnt=0){
        if(n%i==0){
            while(n%i==0)n/=i,cnt++;
            if(i%4==1)ans*=2*cnt+1;
        }
    }
    if(n>1&&n%4==1)ans*=2*1+1;
    printf("%d",4*ans); 
    return 0;
}

洛谷P2529 [SHOI2001]击鼓传花

题目描述

HC(Happy Child )小朋友最近经常在教室里跟同学一起玩击鼓传花的游戏,规则是第\(n\)个拿到花的小朋友必须说出\(n!\)最后一位非\(0\)的数字,如此循环游戏,如果谁讲错了就得罚唱一支歌曲。
经过几次游戏,HC小朋友认为只要把前一个小朋友说得数字去乘以\(n\),说出得到的数的最后一位非\(0\)的数字就可以了,可惜HC小朋友这次轮到了第\(15\)个,结果被罚了唱歌(应该是\(8\),但是HC小朋友却说了\(3\))。
HC小朋友不希望这样的事情再次发生,所以希望你能编写一个程序,能够计算出\(n!\)的最后一位非\(0\)的数字。

输入输出格式

输入格式:

输入有\(5\)行,第\(i(1≤i≤5)\)行是一个\(n(1≤n≤10^{100}\))。

输出格式:

输出有\(5\)行。
第I行对应输入中第I行的n的阶乘的最后一位非\(0\)的数字。

解题思路

下面所有等号的意义是最后一位非零数相等。

观察得(关键步骤):

\((1) (1*2*3*4*6*7*8*9)%10=6\),而\(6^k %10=6(k\)\(N)\)

\((2) p*5=p*8\)

第二步的证明:
\(p*5=p*10/2=p/2\)
乘到\(5\),则必然已经是\(4\)的倍数。
\(2/2=6,4/2=2,6/2=8,8/2=4\)
\(2*8=6,4*8=2,6*8=8,8*8=4\)
证毕。

\(0.\)于是,将所有\(5\)的倍数剔除掉(留待后面计算)后,先算出个位数(除去\(5\))的乘积\(%10\)的结果
此时忽略掉的问题是:
\(1.\)十位数及以上的影响
\(2. 5\)的倍数的影响
其中,\(5\)的倍数影响有两方面:
\(2.(1)5\)本身
\(2.(2)\)除去\(5\)的其他因子影响
\(2.2\)可以通过回到\(0\)递归实现。
注意到,\(6*8=8,1*8=8\)\(8^{[0,1,2,3]}=1,8,4,2\)。所以,\(2.1\)\(1\)可以通过一个\(pre\)数组实现。可以预处理出\(pre\)数组为\([6,8,4,2]\)

举个例子

\(n=917\)
\(n!=(1*2*3*4*6*7*8*9*11*12*13*14*16*17*18*19*...*916)*(5*10*...*915)\)

\(=(6*6*...*6*911*912*913*914*916)*(5^{\left\lfloor 917\over 5\right\rfloor})*(1*2*3*4*6*7*8*9*...*\left\lfloor 917\over 5\right\rfloor)\)

\(=(1*2*3*4*6)*6*(8^{\left\lfloor 917\over 5\right\rfloor})(1*2*3*4*6*7*8*9*...*\left\lfloor 917\over 5\right\rfloor)\)

其中,\(6*(8^{\left\lfloor 917\over 5\right\rfloor})\)可由\(pre\)数组推得;\((1*2*3*4*6*7*8*9*...*\left\lfloor 917\over 5\right\rfloor)\)则可由递归算出。
问题得解。

AC代码

fre=[6,8,4,2]
for j in range(1,6):
    cnt=0
    ans=1
    n=int(input())
    if(n==1):
        print(1)
    else:
        while(n>0):
            for i in range(1,n%10+1):
                if(i!=5):
                    ans*=i
            n//=5
            ans*=fre[n%4]
            ans%=10
        print(ans)

CF1091D New Year and the Permutation Concatenation

题目描述

Let \(n\) be an integer. Consider all permutations on integers \(1\) to \(n\) in lexicographic order, and concatenate them into one big sequence \(p\). For example, if \(n=3\), then \(p=[1,2,3,1,3,2,2,1,3,2,3,1,3,1,2,3,2,1]\). The length of this sequence will be \(n⋅n!\).
Let \(1≤i≤j≤n⋅n!\)be a pair of indices. We call the sequence \((p_i,p_{i+1},…,p_{j−1},p_j)\)
a subarray of \(p\). Its length is defined as the number of its elements, i.e., \(j−i+1\). Its sum is the sum of all its elements, i.e., \(\sum_{k=i}^j p_k\).
You are given \(n\). Find the number of subarrays of \(p\)of length \(n\)having sum \(n(n+1)/2\). Since this number may be large, output it modulo \(998244353\)(a prime number).

输入输出格式

输入格式:

The only line contains one integer \(n(1≤n≤10^6)\), as described in the problem statement.

输出格式:

Output a single integer — the number of subarrays of length \(n\) having sum \(n(n+1)/2\), modulo \(998244353\).

解题思路

\(p\)的选取:不重不漏、连续的\(1-n\)的排列。
首先,第一个数字不同的排列间必然不能产生序列\(p\)。原因:下一个排列的所有数字必然不全位于上一个排列的后面。
所以可以只考虑第一个数字为\(k\)的情况,最后乘以\(k\)即可。

\(ans[i]\)\(n=i\)时符合条件的排列种数。

\(n=k\)已选出合适排列(称为上一级排列),则考虑\(n=k+1\)时,放进新来的\(k+1\)后,有多少种符合题意的子列。
放进新来的\(k+1\)后,其实是向原序列中头部分配了\(k+1\),也即向\(ans[k]\)几乎均匀插入\(k+1\)

故,只有两种可以构成题目中子列的方式:
\((1)\)所有上一级排列之中加上\(k+1\)的新排列(\(ans[k]\)种)
\((2)\)所有头部为\(k+1\)的新形成的排列(\(k!\)种)
其中,这两种方式重复的种数为所有元素降序排列的种数(\(1\)种)。

故得到递推关系式:\(ans[i]=(ans[i-1]+(n-1)!-1)*i\)

AC代码

#include<stdio.h>
long long jc[1000010]={1,1},ans[100010]={0,1},w=998244353;
int main(){
    int i,n;
    scanf("%d",&n);
    for(i=2;i<=n;i++){
        jc[i]=jc[i-1]*i%w;
        ans[i]=(ans[i-1]-1+jc[i-1])*i%w;
    }
    printf("%I64d",ans[n]);
    return 0;
}

转载于:https://www.cnblogs.com/Potassium/p/10226362.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值