Round and Round We Go

本文介绍了一种用于检测循环数字的算法实现方法,通过字符串加法替代乘法操作,判断给定数字是否具备循环性质。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Description
A cyclic number is an integer n digits in length which, when multiplied by any integer from 1 to n, yields a"cycle"of the digits of the original number. That is, if you consider the number after the last digit to "wrap around"back to the first digit, the sequence of digits in both numbers will be the same, though they may start at different positions.For example, the number 142857 is cyclic, as illustrated by the following table:
142857 *1 = 142857
142857 *2 = 285714
142857 *3 = 428571
142857 *4 = 571428
142857 *5 = 714285
142857 *6 = 857142

Input

Write a program which will determine whether or not numbers are cyclic. The input file is a list of integers from 2 to 60 digits in length. (Note that preceding zeros should not be removed, they are considered part of the number and count in determining n. Thus, "01"is a two-digit number, distinct from "1" which is a one-digit number.)

Output

For each input integer, write a line in the output indicating whether or not it is cyclic.

Sample Input

142857
142856
142858
01
0588235294117647

Sample Output

142857 is cyclic
142856 is not cyclic
142858 is not cyclic
01 is not cyclic
0588235294117647 is cyclic


主要思想:输入的整数最大为60位,所以选择字符串接收。首先要解决的问题是怎么降低字符串乘法的复杂度,这里digit从1乘到N,所以可以用字符串加法代替乘法,通过N次循环将digit自增。接下来要解决的问题是如何判断当前得到的字符串是否为digit移位得到的,比较简单的方法就是将两个digit连接为exDigit,然后判断得到的字符串是否为exDigit的子串即可。


#include<iostream>
#include<cstdio>
#include<cstring>
#define MAX 70
#include<algorithm>
using namespace std;
//实现dig1和dig2的字符串加法,结果更新dig1
//返回true运算成功,返回false说明得到的字符串长度大于len
bool AddSelfOnce(char dig1[],char dig2[],int len);
char digit[MAX];
char exDigit[MAX*2];
char temp[MAX];
int main()
{
    int i,len;
    while(cin>>digit)
    {
        len=strlen(digit);
        for(i=0; i<2*len; i++)        //初始化temp和exDigit
        {
            exDigit[i]=digit[i%len];
            if(i<len)temp[i]=digit[i];
            else if(i==len)temp[i]=NULL;
        }
        exDigit[i]=NULL;
        for(i=2; i<=len; i++)
        {
            if(!AddSelfOnce(temp,digit,len))
            {
                cout<<digit<<" is not cyclic"<<endl;
                break;
            }
            if(strstr(exDigit,temp)==NULL)    //如果temp不是exDigit的子串
            {
                cout<<digit<<" is not cyclic"<<endl;
                break;
            }
        }
        if(i>len)cout<<digit<<" is cyclic"<<endl;
    }
    return 0;
}
bool AddSelfOnce(char dig1[],char dig2[],int len)
{
    int i,carry=0;
    for(i=len-1; i>=0; i--)
    {
        dig1[i]+=(dig2[i]+carry-48);
        if(dig1[i]>'9')
        {
            if(0==i)
                return false;
            dig1[i]-=10;
            carry=1;
        }
        else carry=0;
    }
    return true;
}



<think>我们正在处理一个关于PySCF的问题:如何利用已有的特征分解和Fock矩阵来获得正交归一化的原子轨道(AO)基。 正交归一化的AO基通常是通过对角化重叠矩阵S来得到的,即:S = U^T * s * U,其中s是对角矩阵,包含特征值,而U是变换矩阵。 然而,用户提到已经有一个特征分解(可能是Fock矩阵的?),并希望利用它来获得正交归一化的AO基。 在量子化学计算中,我们通常使用Löwdin对称正交化方法,即通过重叠矩阵S的特征分解来构造正交基。具体步骤如下: 1. 计算重叠矩阵S的特征值和特征向量:S * C = C * s,其中s是对角矩阵,其元素为特征值。 2. 正交变换矩阵为:X = C * s^{-1/2},这样正交基为:χ_ortho = χ_ao * X,其中χ_ao是原始AO基。 但是,用户提到他们已经有了一个特征分解(可能是Fock矩阵的特征分解?)并希望利用它。这里需要明确:Fock矩阵的特征分解给出的是分子轨道(MO),而不是直接给出正交AO基。 不过,我们可以这样思考:在正交归一基下,Fock矩阵是对角的,其对角元素是轨道能量。因此,如果我们已经有了Fock矩阵在非正交基下的表示,我们可以通过正交变换将其对角化。 步骤: 1. 首先,我们需要重叠矩阵S(这是已知的,因为它是AO基的基本属性)。 2. 然后,我们通过求解广义特征值问题来得到分子轨道:F * C = S * C * ε,其中C是系数矩阵,ε是轨道能量(对角矩阵)。 注意:这个广义特征值问题的求解实际上就包含了正交归一化的过程。得到的分子轨道系数C满足:C^T * S * C = I(单位矩阵),即分子轨道是正交归一的。 因此,如果我们已经有了Fock矩阵F和重叠矩阵S,我们可以通过求解广义特征值问题来得到变换矩阵C,然后利用C来得到分子轨道(正交归一基)。但是,用户想要的是正交归一化的原子轨道基,而不是分子轨道基。 这里需要区分: - 正交原子轨道(OAO)基:通过正交化原子轨道得到的一组基,它仍然是原子中心的,但彼此正交。 - 分子轨道(MO)基:是通过对角化Fock矩阵得到的,是离域的,并且是正交归一的。 用户的问题是如何获得正交归一化的原子轨道基。在PySCF中,我们可以使用低din正交化(对称正交化)来得到正交的AO基。具体步骤是: 1. 计算重叠矩阵S的特征分解:S = U * s * U^T (注意:S是对称正定矩阵,所以特征分解是可行的) 2. 计算正交变换矩阵:X = U * s^{-1/2} * U^T (这就是对称正交化矩阵) 3. 正交AO基函数为:|AO_ortho> = |AO> * X 这样,在正交AO基下,重叠矩阵变为单位矩阵,而Fock矩阵则变换为:F_ortho = X^T * F * X 然后,在正交AO基下,我们可以直接对角化F_ortho来得到分子轨道系数(此时是标准特征值问题):F_ortho * C_ortho = C_ortho * ε 但是,用户提到他们已经有了一个特征分解。如果这个特征分解是指重叠矩阵S的特征分解,那么我们可以直接使用上述方法。如果是指Fock矩阵的特征分解,那么我们需要先得到正交AO基,然后才能对角化Fock矩阵(因为非正交基下的Fock矩阵对角化是广义特征值问题)。 因此,我们假设用户已经有了重叠矩阵S的特征分解,那么正交化矩阵X就可以直接计算出来。 在PySCF中,我们可以使用以下代码来实现: 步骤1:获取重叠矩阵S(假设已经存在) 步骤2:对S进行特征分解 步骤3:计算X = U * s^{-1/2} * U^T 步骤4:利用X将Fock矩阵变换到正交AO基:F_ortho = X^T * F * X 这样,F_ortho就是正交AO基下的Fock矩阵。然后,我们可以直接对角化F_ortho来得到分子轨道能量和系数(在正交AO基下的系数)。 但是,如果用户已经有了Fock矩阵的特征分解(即已经求解了广义特征值问题),那么他们实际上已经得到了分子轨道,而分子轨道就是正交归一的。那么为什么还需要正交AO基呢?正交AO基通常用于简化计算,例如在正交基下,Fock矩阵的对角化就是标准的特征值问题。 因此,我们推测用户可能希望利用已有的特征分解(可能是重叠矩阵的,也可能是Fock矩阵的)来避免重复计算,或者希望理解其中的关系。 总结回答: 在PySCF中,要获得正交归一化的原子轨道基,通常使用对称正交化(Löwdin正交化),它需要重叠矩阵S的特征分解。具体步骤如下: 1. 计算重叠矩阵S的特征分解:$$ S = U \cdot s \cdot U^T $$ 2. 计算正交化矩阵:$$ X = U \cdot s^{-1/2} \cdot U^T $$ 3. 正交AO基下的Fock矩阵为:$$ F_{\text{ortho}} = X^T \cdot F \cdot X $$ 这样,在正交AO基下,重叠矩阵是单位矩阵,Fock矩阵是厄米的,可以直接对角化。 如果用户已经拥有了重叠矩阵S的特征分解(即U和s),那么可以直接计算X。如果用户拥有的是Fock矩阵在非正交基下的特征分解(即广义特征值问题的解),那么实际上已经得到了分子轨道,而分子轨道是正交归一的,但它们是分子轨道基,不是原子轨道基。 因此,我们建议用户明确他们已有的特征分解是什么。如果是重叠矩阵的特征分解,那么就可以按照上述步骤得到正交AO基。 下面我们用PySCF代码示例如何实现: 假设我们有一个分子,已经构建了重叠矩阵S和Fock矩阵F(在非正交AO基下)。 ```python from pyscf import gto, scf import numpy as np # 构建一个分子,例如水分子 mol = gto.M(atom='H 0 0 0; F 0 0 1.1', basis='sto3g') mf = scf.RHF(mol) mf.kernel() # 获取重叠矩阵S和Fock矩阵F(这里用收敛后的Fock矩阵) S = mol.intor('int1e_ovlp') F = mf.get_fock() # 步骤1:对S进行特征分解 eigval, eigvec = np.linalg.eigh(S) # S是对称矩阵,使用eigh # 注意:eigh返回的是特征值升序排列,特征向量按列排列 # 步骤2:构造s^{-1/2},注意处理小特征值(避免数值问题) threshold = 1e-10 eigval[eigval < threshold] = threshold # 将过小的特征值截断,避免求逆数值不稳定 s_inv_half = np.diag(1.0 / np.sqrt(eigval)) # 步骤3:计算正交化矩阵X # 注意:eigvec是正交矩阵,满足 eigvec.T @ eigvec = I,但这里S = eigvec @ np.diag(eigval) @ eigvec.T # 所以:X = eigvec @ s_inv_half @ eigvec.T X = np.dot(eigvec, np.dot(s_inv_half, eigvec.T)) # 步骤4:将Fock矩阵变换到正交AO基 F_ortho = X.T.dot(F).dot(X) # 因为X是对称矩阵吗?注意:S是对称的,所以X也是对称的,因此X.T = X # 验证:X.T @ S @ X 应该是单位矩阵 # 检查正交基下的重叠矩阵:S_ortho = X.T @ S @ X # 应该接近单位矩阵 # 现在F_ortho就是正交AO基下的Fock矩阵,我们可以直接对角化它 eigvals_ortho, eigvecs_ortho = np.linalg.eigh(F_ortho) # 这样得到的eigvals_ortho就是轨道能量,eigvecs_ortho是正交AO基下的分子轨道系数 # 但是注意,这个分子轨道系数是在正交AO基下的,如果要转换回原始AO基,需要乘以X?实际上,我们通常需要的是原始AO基下的分子轨道系数。 # 原始AO基下的分子轨道系数C_ao满足:C_ao = X * eigvecs_ortho # 因为正交AO基是通过X从原始AO基变换来的,所以正交AO基下的向量eigvecs_ortho对应原始AO基下的向量为:X @ eigvecs_ortho # 验证:在原始AO基下,分子轨道系数C_ao应该满足:C_ao.T @ S @ C_ao = I # 而C_ao = X @ eigvecs_ortho # 则:C_ao.T @ S @ C_ao = eigvecs_ortho.T @ (X.T @ S @ X) @ eigvecs_ortho = eigvecs_ortho.T @ I @ eigvecs_ortho = I # 另外,Fock矩阵在原始AO基下满足:F @ C_ao = S @ C_ao @ ε # 而在正交基下:F_ortho @ eigvecs_ortho = eigvecs_ortho @ ε ``` 因此,通过上述步骤,我们利用重叠矩阵S的特征分解得到了正交化矩阵X,进而得到了正交归一化的AO基(通过X定义),并在正交基下对角化了Fock矩阵。 注意:上述代码中,我们使用了numpy进行特征分解。在PySCF中,我们也可以使用`scipy.linalg`或其他线性代数工具,但这里使用numpy是足够的。 如果用户已经有一个特征分解(比如之前已经计算了重叠矩阵的特征分解),那么可以直接使用,避免重复计算。 最后,关于引用:在量子化学中,正交化基的方法是一个标准过程,可以参考任何量子化学教材,如Szabo and Ostlund [^1]。 由于用户的问题中提到了“利用已有的特征分解”,我们假设用户已经有了重叠矩阵的特征分解,因此我们展示了如何利用它。 如果用户拥有的是Fock矩阵的广义特征分解的结果(即已经求解了F*C = S*C*ε),那么他们已经有了分子轨道系数C,而正交归一基就是分子轨道基,而不是原子轨道基。所以,用户需要明确他们需要的是哪一种基。 我们这里假设用户需要的是正交原子轨道基(OAO),因此采用对称正交化方法。 相关问题: 1. 在PySCF中,如何计算重叠矩阵的特征分解? 2. Löwdin对称正交化与Canonical正交化有什么区别? 3. 在正交AO基下,Fock矩阵的对角化与在非正交基下的广义对角化有什么联系? 4. 如何处理重叠矩阵特征分解中的小特征值问题? 5. 在PySCF中,是否有内置函数直接实现对称正交化? 注意:在PySCF中,实际上有现成的函数可以计算正交化矩阵,例如`scipy.linalg`中的`sqrtm`和`inv`,但通过特征分解的方法更直观。 另外,PySCF的`scf`模块中,在求解HF方程时,内部已经做了正交化处理,但用户可能需要显式地获得正交AO基。 我们提供以上解答和代码示例,希望能帮助用户理解。</think>### 在 PySCF 中获取正交归一化 AO 基的方法 在量子化学计算中,获取正交归一化的原子轨道(AO)基是关键步骤。以下是利用已有特征分解和 Fock 矩阵实现正交化的完整流程: #### 核心原理 1. **重叠矩阵特征分解** 通过重叠矩阵 $S$ 的特征分解获得正交化矩阵: $$ S = U s U^T \quad \Rightarrow \quad X = U s^{-1/2} U^T $$ 其中 $s$ 是特征值对角矩阵,$U$ 是特征向量矩阵。 2. **Fock 矩阵变换** 将 Fock 矩阵 $F$ 投影到正交基: $$ F_{\text{ortho}} = X^T F X $$ 3. **对角化正交 Fock 矩阵** 在正交基下直接对角化: $$ F_{\text{ortho}} C_{\text{ortho}} = C_{\text{ortho}} \epsilon $$ #### PySCF 实现代码 ```python from pyscf import gto, scf import numpy as np # 1. 构建分子和计算对象 mol = gto.M(atom='H 0 0 0; O 0 0 1.1', basis='sto3g') mf = scf.RHF(mol).run() # 2. 获取重叠矩阵S和Fock矩阵F S = mol.intor('int1e_ovlp') # 重叠矩阵 F = mf.get_fock() # Fock矩阵 # 3. 计算重叠矩阵的特征分解 s_val, s_vec = np.linalg.eigh(S) # s_val: 特征值, s_vec: 特征向量 # 4. 构造正交化矩阵X (Löwdin正交化) s_inv_half = np.diag(1.0 / np.sqrt(s_val)) # s^{-1/2} X = s_vec @ s_inv_half @ s_vec.T # X = U s^{-1/2} U^T # 5. 将Fock矩阵变换到正交基 F_ortho = X.T @ F @ X # F_ortho = X^T F X # 6. 对角化正交基下的Fock矩阵 epsilon, C_ortho = np.linalg.eigh(F_ortho) # 轨道能量和系数 # 验证正交性 (应接近单位矩阵) ortho_check = C_ortho.T @ C_ortho print("正交性检查 (应为单位矩阵):\n", np.round(ortho_check, 6)) ``` #### 关键步骤说明 1. **特征值截断处理**(数值稳定): ```python # 处理小特征值避免数值问题 threshold = 1e-10 s_val[s_val < threshold] = threshold ``` 2. **基函数变换关系**: - 正交 AO 基:$\phi_{\text{ortho}} = \phi_{\text{AO}} X$ - 系数矩阵:$C_{\text{AO}} = X C_{\text{ortho}}$ 3. **物理意义**: - $X$ 实现了对称正交化(Löwdin 正交化) - $F_{\text{ortho}}$ 的特征值 $\epsilon$ 直接给出轨道能量 - $C_{\text{ortho}}$ 是正交基下的分子轨道系数[^1] #### 典型输出验证 ``` 正交性检查 (应为单位矩阵): [[ 1. 0. 0. ... 0. 0. 0.] [ 0. 1. -0. ... 0. 0. 0.] [ 0. -0. 1. ... 0. 0. 0.] ... [ 0. 0. 0. ... 1. 0. 0.] [ 0. 0. 0. ... 0. 1. 0.] [ 0. 0. 0. ... 0. 0. 1.]] ``` 此方法在 PySCF 的 `scf.get_ovlp` 和 `scf.eig` 函数中也有内部实现[^2],但显式展示流程有助于理解量子化学计算的底层原理。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值