num1:C++
code:#include
include
include
include
using namespace std;
const int p=19260817;
int a[10100];
int b[10100];
char a1[10100];
char b1[10100];
int l1,l2;
int len1,len2;
long long x,y;
long long pow2(long long a,long long b)
{
long long res=1;
for(;b;b>>=1,a=aa%p) if(b&1) res=resa%p;
return res%p;
}
void calculet_1()
{
long long num=0;
for(int i=len1;i<=len1+8;i++)
num*=10,num+=a[i];
num%=p;
for(int i=len1+8;i>=len1;i--)
{
int now=num%10;num/=10;
a[i]=now;
}
for(int i=0;i<=8;i++) if(a[len1+i]!=0){len1+=i;break;}
}
void calculet_2()
{
long long num=0;
for(int i=len2;i<=len2+8;i++)
num*=10,num+=b[i];
num%=p;
for(int i=len2+8;i>=len2;i--)
{
int now=num%10;num/=10;
b[i]=now;
}
for(int i=0;i<=8;i++) if(b[len2+i]!=0){len2+=i;break;}
}
signed main()
{
// freopen("testdata.in","r",stdin);
// freopen("1.out","w",stdout);
scanf("%s",a1);
scanf("%s",b1);
// printf("%s\n",b1);
l1=strlen(a1);
l2=strlen(b1);
for(int i=0;i<l1;i++)
a[i]=a1[i]-'0';
for(int i=0;i<l2;i++)
b[i]=b1[i]-'0';
while(l1-len1>=10) calculet_1();
while(l2-len2>=10) calculet_2();
for(int i=len1;i<l1;i++) x*=10,x+=a[i];
for(int i=len2;i<l2;i++) y*=10,y+=b[i];
x%=p;y%=p;
// printf("%lld\n",y);
if(x0){puts("0");return 0;}
if(y0){puts("Angry!");return 0;}
long long ans=pow2(y,p-2);
// printf("%lld\n",ans);
ans=(ans*x)%p;
printf("%lld",ans);
return 0;
}
解题思路:利用模运算的性质和费马小定理来解决大数除法在模 p=19260817 下的计算问题。首先,将输入的大数字符串转换为数组形式,并去除前导零。然后,通过自定义的 calculet_1 和 calculet_2 函数(注意这里可能是 calculate_1 和 calculate_2 的拼写错误),对大数进行必要的处理,确保它们在模 p 下有有效的表示。最后,利用费马小定理计算模逆元,从而完成模运算下的除法,并输出结果。
num2:C++
code:#include
include
include
include
using namespace std;
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int t;
cin >> t;
while (t--) {
long long l, r;
cin >> l >> r;
int count = 0;
for (long long r_prime = l; r_prime <= r; ++r_prime) {
bool found = false;
for (long long l_prime = r_prime; l_prime >= l; --l_prime) {
if (gcd(l_prime, r_prime) == 1) {
found = true;
count++;
break;
}
}
if (!found) continue;
}
cout << count << endl;
}
return 0;
}
解题思路:首先读取测试数据组数,然后对于每组数据,读取一个区间范围。接下来,通过双重循环遍历区间内的所有数对,其中外层循环变量从区间左端点到右端点递增,内层循环变量从外层循环变量递减到区间左端点。对于每对数,计算它们的最大公约数,如果最大公约数为1,则这对数互质,计数器加一。最后,输出每组数据中互质数对的总数。这种方法虽然直观,但效率较低,特别是对于大数据集。(但该代码存在一定问题,望指点)
num3:C++
code:#include
include
include
include
using namespace std ;
bool vis[1000005];
int num[6000],tot=0;
void read( void )
{
for(int i=2;i<=800;i++)
if(!vis[i])
{
num[++tot]=i;
for(int j=i*i;j<=800;j+=i)
vis[j]=true;
}
for(int i=801;i<=50000;i++)
for(int j=1;j<=tot;j++)
if(i%num[j]==0)break;
else if(num[j]*num[j]>=i){num[++tot]=i;break;}
}
int main()
{
//freopen("prime.in","r",stdin);
//freopen("prime.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
read( );
memset(vis,0,sizeof(vis));
for(int k=1;k<=tot&&num[k]<=sqrt(m);k++)
{
int t=num[k]num[k];
if(t<n)t=n/num[k]num[k];
if(t<n)
if(t<=m-num[k])t+=num[k];
else continue;
for(;t<=m;)
{
vis[t-n]=true;
if(t==num[k])vis[t-n]=false;
if(t<=m-num[k])t+=num[k];
else break;
}
}
if(n==1)vis[0]=true;
int ans=0;
for(int i=0;i<=m-n;i++)
if(!vis[i])ans++;
cout<<ans;
return 0;
}
解题思路:首先通过埃拉托斯特尼筛法预处理出小于等于50000的素数。接着,对于给定的范围[n, m],利用已筛选出的素数,标记出该范围内所有差为素数的数对(x, y=x+p)中的y值(其中x在[n, m-p]内,p为素数)。特别地,对于每个素数p,从其在n范围内的最小完全平方倍数开始,以p为步长标记,同时排除p本身造成的重复标记。最后,统计未被标记的[n, m]内的数,即为与n构成素数差的数的个数,并输出结果。
num4:C++
code:#include<bits/stdc++.h>
using namespace std;
int x,y,p,ans=1,a;
int main()
{
cin>>x>>y;
if(y%x!=0)cout<<0;
else
{
p=y/x;
a=2;
while(p!=1)
{
while(p%a!=0)a++;
while(p%a==0)p/=a;
a++;ans*=2;
}
cout<<ans;
}
return 0;
}
解题思路:首先读取两个整数x和y,判断y是否能被x整除,若不能则直接输出0。若能整除,则计算商p(即y除以x的结果),接着对p进行质因数分解。在质因数分解过程中,每找到一个质因数a,就将答案ans乘以2(因为每个质因数可以选择出现或不出现两种可能,除非p本身就是质数且等于该质因数,此时不应额外乘以2以避免重复计算)。当p被分解到1时,循环结束,最终输出累乘得到的ans作为x和y的最大公约数的不同质因数个数所对应的可能组合数。
num5:C++
code:#include
include
include
include
include
using namespace std;
long long gcd(long long a, long long b) {
while (b != 0) {
long long temp = b;
b = a % b;
a = temp;
}
return a;
}
long long lcm(long long a, long long b) {
return a / gcd(a, b) * b;
}
int main() {
int n, m;
cin >> n >> m;
vector<long long> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
sort(a.begin(), a.end());
vector<int> best_sequence;
long long current_lcm = 1;
for (int i = 0; i < n; ++i) {
if (lcm(current_lcm, a[i]) <= m) {
current_lcm = lcm(current_lcm, a[i]);
best_sequence.push_back(i + 1);
} else {
break;
}
}
cout << current_lcm << " " << best_sequence.size() << endl;
for (int index : best_sequence) {
cout << index << " ";
}
cout << endl;
return 0;
}
解题思路:读取整数n(数列长度)和m(限制条件),接着读取n个数存入数组。对这些数进行排序后,尝试依次计算当前最小公倍数(LCM)与数组中每个数的LCM,只要结果不超过m,就更新当前LCM并将该数加入最优序列。一旦某个数的加入导致LCM超过m,就停止搜索。最后,输出找到的最大LCM值、最优序列的长度以及序列中的元素编号。这个过程旨在找到满足LCM限制的最长子序列。(该代码仍存在问题)
num6:C++
code:#include
include
include <unordered_set>
include
include
using namespace std;
vector
vector
for (int i = 2; i <= sqrt(num); ++i) {
if (num % i == 0) {
divisors.push_back(i);
if (i != num / i) {
divisors.push_back(num / i);
}
}
}
sort(divisors.begin(), divisors.end());
return divisors;
}
int findGenerator(const vector
int minVal = *min_element(arr.begin(), arr.end());
int start = minVal;
const int MAX_ITERATIONS = 1000000;
while (MAX_ITERATIONS--) {
unordered_set<int> reachable;
reachable.insert(start);
bool allReachable = true;
for (int num : arr) {
if (reachable.count(num)) continue;
vector<int> divisors = getDivisors(num);
bool reachableFromStart = false;
for (int divisor : divisors) {
int candidate = start + (num - (num % divisor)) / divisor * divisor - num;
if (candidate >= 0 && candidate % divisor == 0 && reachable.count(start + candidate / divisor)) {
reachableFromStart = true;
break;
}
}
if (!reachableFromStart) {
allReachable = false;
break;
}
}
if (allReachable) return start;
start++;
}
return -1; // 如果没有找到满足条件的x,则返回-1
}
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
cout << findGenerator(a) << endl;
}
return 0;
}
解题思路:针对每个测试用例,首先读取数列长度和数列元素。然后,定义一个函数findGenerator来寻找一个“生成元”x,使得通过不断加x或x的某个除数倍到自身,可以从x到达数列中的每个元素。这通过检查数列中每个元素是否可从x通过一系列加法操作达到来实现。为了避免重复计算和无效搜索,使用了一个哈希集合reachable来记录已可达的元素。若在一定迭代次数内找到这样的x,则返回它;否则,返回-1表示未找到。此过程旨在解决一个关于数列可达性的问题。(该代码存在一定问题)
感受:此次训练题目难度上升很大,还需要学习进步。

浙公网安备 33010602011771号