NEUQ-acm第二期训练Week4——代码源div2

501RSA

题目描述

RSA算法选择两个不同质数的积作为模数。现在有两个正整数 A,B,如果它们是不同的质数,则判定为 full credit;否则,如果A⋅B不是任意大于1的整数的平方的整数倍,则判定 partial credit;否则判定为no credit。

输入格式

一行两个正整数 A,B。

输出格式

full credit 或 partial credit 或 no credit。

样例输入1

13 23

样例输出1

full credit

样例输入2

3 3

样例输出2

no credit
数据规模

所有数据保证 2 ≤ A , B ≤ 1 0 12 2≤A,B≤10^{12} 2A,B1012

思路

判断是否为素数,按条件输出,发现判断a*b时数据范围超了;
故判断a与b的因子个数,如果因子出现偶数或者该因子可以是平方的形式,那么就是no credit
怎么统计因子的个数,由于数据太大,用map即可

代码

#include <bits/stdc++.h>
using namespace std;
long long a,b;
//long long x;
bool zhishu(long long s){
    int flag = 0;
    if(s==2)  return true;
    for(long long i = 2; i <= sqrt(s); i++){
        //cout << i << endl;
        //if(i==545527) cout << "@";
        if(s%i==0){
            flag=1;
            //cout << "#" ;
            break;
        }
    }
    if(flag==1)  return false;
    else  return true;
}
map < long long, long long> y;
void yinzi(long long s){
    for(long long i = 2; i <= sqrt(s); i++){
        if(s%i==0){
            y[i]++;
            y[s/i]++;
        }
    }
}
int main(){
    cin >> a >> b;
    //cout << sqrt(a) << endl;
    //zhishu(a);
    if(a!=b && zhishu(a) && zhishu(b))  cout << "full credit" << endl;
    else{
        //x = a*b;
        //cout << x;
        yinzi(a);
        yinzi(b);
        int flag = 0;
        for(auto i = y.begin(); i!=y.end(); i++){
            long long x = sqrt(i->first);
            if(x*x==i->first || i->second>1){
                flag=1;
                //cout << i->second;
                break;
            }
        }
        if(flag==0 && a!=b)  cout << "partial credit" << endl;
        else  cout << "no credit" << endl;
    }
}

502数组操作

题目描述

给你一个有 n n n 个元素的数组 a a a 。你可以对它进行如下操作,次数不限。

从一个偶数大小为 2 k 2k 2k 的数组中选择一些从位置 l l l开始的子数组 ( 1 ≤ l ≤ l + 2 ⋅ k − 1 ≤ n , k ≥ 1 ) (1≤l≤l+2⋅k−1≤n , k≥1) (1ll+2k1n,k1) ,对于 0 0 0 k − 1 k−1 k1(包括)之间的每一个 i i i ,将值 a l + k + i a_{l+k+i} al+k+i 分配给 a l + i a_{l+i} al+i

例如,如果 a = [ 2 , 1 , 3 , 4 , 5 , 3 ] a=[2,1,3,4,5,3] a=[2,1,3,4,5,3] ,然后选择 l = 1 l=1 l=1 k = 2 k=2 k=2 ,应用这个操作,数组将变成 a = [ 3 , 4 , 3 , 4 , 5 , 3 ] a=[3,4,3,4,5,3] a=[3,4,3,4,5,3]

请找出使数组中所有元素相等所需的最少操作数(可能是零)。

输入格式

输入由多个测试用例组成。第一行输入一个整数 t ( 1 ≤ t ≤ 2 × 1 0 4 ) t(1≤t≤2×10^4) t(1t2×104)表示测试用例的数量。

每个测试用例的包含 ( n + 1 ) (n+1) (n+1) 个整数:

第一个整数 n ( 1 ≤ n ≤ 2 × 1 0 5 ) n(1≤n≤2×10^5) n(1n2×105) 表示数组的长度。

此后 n n n 个整数 a 1 , a 2 , . . . , a n ( 1 ≤ a i ≤ n ) a_1,a_2,...,a_n(1≤a_i≤n) a1,a2,...,an(1ain) 表示数组的元素。

输出格式

输出 t t t 行,每行一个整数表示用给定的操作使数组中所有元素相等所需的最小操作数。

样例输入

5
3 1 1 1
2 2 1
5 4 4 4 2 4
4 4 2 1 3
1 1

样例输出

0
1
1
2
0
数据规模

保证所有测试用例的 n 之和不超过 200000。

提示

在第一个测试中,所有元素都是相等的,因此不需要任何操作。

在第二个测试中,你可以应用一个操作, k = 1 , l = 1 k=1,l=1 k=1l=1,设置 a 1 ← a 2 a_1←a_2 a1a2 ,通过 1 1 1 个操作,数组变成 [ 1 , 1 ] [1,1] [1,1]

在第三个测试中,你可以应用一个操作, k = 1 , l = 4 k=1,l=4 k=1l=4,设置 a 4 ← a 5 a_4←a_5 a4a5 ,然后数组变成 [ 4 , 4 , 4 , 4 , 4 ] [4,4,4,4,4] [4,4,4,4,4]

在第四个测试中,你可以应用一个操作, k = 1 , l = 3 k=1,l=3 k=1l=3,设置 a 3 ← a 4 a_3←a_4 a3a4 ,数组变成 [ 4 , 2 , 3 , 3 ] [4,2,3,3] [4,2,3,3],然后你可以应用另一个操作, k = 2 , l = 1 k=2,l=1 k=2l=1,设置 a 1 ← a 3 , a 2 ← a 4 a_1←a_3,a_2←a_4 a1a3,a2a4, 数组变成 [ 3 , 3 , 3 , 3 ] [3,3,3,3] [3,3,3,3]

在第五次测试中,只有一个元素,因此不需要任何操作。

思路

最后变成的数组一定是最后一位的值,所以我们倒着来,每次可以使与a[n]相等的后几位数赋给前面的,直到所有的都赋值完

代码

#include <bits/stdc++.h>
using namespace std;
const int Max = 2e5+5;
int t,n;
int a[Max];
int main(){
    cin >> t;
    for(int i = 1; i <= t; i++){
        cin >> n;
        for(int j = 1; j <= n; j++)  cin >> a[j];
        int val = a[n];
        int num =1, ans = 0;
        for(int j = n-1; j >= 1; j--){
            if(a[j]==val) num++;
            else{
                j-=num-1;
                num*=2;
                ans++;
            }
        }
        cout << ans << endl;
    }
}

503A-B 数对

题目描述

给出一串数以及一个数字 C ,要求计算出所有 A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。

输入格式

输入共两行。

第一行,两个整数 N, C。

第二行, N 个整数,作为要求处理的那串数。

输出格式

一行,表示该串数中包含的满足 A−B=C 的数对的个数。

样例输入

4 1
1 1 2 3

样例输出

3
数据范围

1 ≤ N ≤ 2 × 1 0 5 , 1 ≤ C ≤ 2 × 1 0 5 1≤N≤2×10^5, 1≤C≤2×10^5 1N2×105,1C2×105, 题目保证输入的 N 个数范围小于 230。

思路

统计每一个数出现的个数,那么a-b=c的个数就是遍历1~maxx-c,对于每一个i都有a[i]*a[i+c]种搭配使得等式成立,每种结果加起来即可

代码

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e7+5;
int n,c;
int a[Max];
int main(){
    cin >> n >> c;
    int maxx = 0;
    for(int i = 1; i <= n; i++){
        int x;
        cin >> x;
        a[x]++;
        maxx = max(maxx,x);
    }
    int ans = 0;
    for(int i = 1; i <= maxx-c; i++){
        if(a[i+c]!=0){
            ans += a[i]*a[i+c];
        }
    }
    cout << ans << endl;
}

504数位计算

题目描述

​ 给出一个整数 n n n,请解决下面的问题:

​ 使 f ( x ) = ( 不超过 x 且与 x 具有相同位数的正整数的个数 ) f(x)=(不超过 x 且与 x 具有相同位数的正整数的个数) f(x)=(不超过x且与x具有相同位数的正整数的个数)

​ 求出 f ( 1 ) + f ( 2 ) + . . . + f ( n ) f(1)+f(2)+...+f(n) f(1)+f(2)+...+f(n) ,结果对 998244353 998244353 998244353 取模。

输入格式

​ 一个整数 N。

输出格式

​ 一个整数——上面问题的答案,并对 998244353 取模。

样例输入1

16

样例输出1

73
样例解释

对从 1 到 9 的每个 x,不超过 x 且与 x 具有相同位数的正整数有 1 , 2 , . . , x 1,2,..,x 1,2,..,x,因此, f ( 1 ) = 1 , f ( 2 ) = 2 , . . . , f ( 9 ) = 9 f(1)=1,f(2)=2,...,f(9)=9 f(1)=1,f(2)=2,...,f(9)=9。对从 10 到 16 的每个 x,不超过 x 且与 x 具有相同位数的正整数有 10 , 11 , . . , x , 10,11,..,x, 10,11,..,x因此, f ( 10 ) = 1 , f ( 11 ) = 2 , . . . , f ( 16 ) = 7 f(10)=1,f(11)=2,...,f(16)=7 f(10)=1,f(11)=2,...,f(16)=7。所以答案为 73。

样例输入2

238

样例输出2

13870

样例输入3

999999999999999999

样例输出3

762062362
数据规模

​ 所有数据保证 1 ≤ N < 1 0 18 1≤N<10^{18} 1N<1018,且 N 是整数。

思路

计算1 ~ 9、10 ~ 99、100 ~ 999…
最后剩余的不足一个区间的尾数单独再算一次,累加即可

代码

#include <bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
long long n;
long long ans;
int main(){
    cin >> n;
    long long t = n;
    long long len = 0;
    while(t){
        t/=10;
        len++;
    }
    //cout << len << endl;
    long long w = 9;
    for(int i = 1; i < len; i++){
        ans = (ans +((w%mod+1)*(w%mod)/2)%mod)%mod;
        w*=10;
    }
    w = n - w/9 +1;
    ans = (ans + ((w%mod)*(w%mod+1)/2)%mod)%mod;
    cout << ans << endl;
}

505新国王游戏

题目描述

又到了 H 国国庆, 国王再次邀请 n 位大臣来玩有奖游戏。上次国庆被众臣吐槽国王小气后,国王决定今年大方点,改变游戏规则且不再参与游戏,免得被大臣们质疑。首先, 他让每位大臣在左、 右手上面分别写下一个正整数。然后让这 n 位大臣排成一排。排好队后, 所有的大臣都会获得国王奖赏的若千金币, 每位大臣获得的金币数分别是:排在该大臣后面的所有人的左手上的数的乘积乘以他自己右手上的数。国王希望所有大臣获得的金币数之和最多,所以他想请你帮他重新安排一下队伍的顺序。

简而言之,给定 n 对数 a i , b i a_i,b_i ai,bi,找到一种排列顺序,使得 b 1 × a 2 ∗ a 3 ∗ … a n + b 2 × a 3 ∗ a 4 ∗ … a n + ⋯ + b n b_1×a_2∗a_3∗…a_n+b_2×a_3∗a_4∗…a_n+⋯+b_n b1×a2a3an+b2×a3a4an++bn 最大,求最大值,由于答案可能很大,需要对 1000000007 1000000007 1000000007 取模

输入格式

第一行,包含一个整数 n。 第二行到第 n+1 行,包含两个整数 a i , b i a_i,b_i ai,bi

输出格式

输出一行,表示按某种排序后的 b 1 × a 2 ∗ a 3 ∗ … a n + b 2 × a 3 ∗ a 4 ∗ … a n + ⋯ + b n b_1×a_2∗a_3∗…a_n+b_2×a_3∗a_4∗…a_n+⋯+b_n b1×a2a3an+b2×a3a4an++bn的最大值对 1000000007 1000000007 1000000007 取模的结果

样例输入

2
1 2
3 4

样例输出

10
说明

只有两种情况:
1.

1 2
3 4

( 2 ∗ 3 ) + 4 = 10 (2∗3)+4=10 (23)+4=10
2.

3 4
1 2

( 4 ∗ 1 ) + 2 = 6 (4∗1)+2=6 (41)+2=6
所以答案为 10

数据限制

对于 100% 的数据,保证 1 ≤ n ≤ 1 0 6 , 1 ≤ a i , b i ≤ 2 30 1≤n≤10^6,1≤a_i,b_i≤2^{30} 1n106,1ai,bi230

思路

先排序,将大臣交换比较哪种情况金币多
排好序后计算结果即可

代码

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e6+5;
const long long  mod = 1000000007;
int n;
struct p{
    long long l,r;
    bool operator<(p b){
        return b.r*(l-1) < r*(b.l-1);
    }
}pai[Max];
long long ans;
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> pai[i].l >> pai[i].r;
    }
    sort(pai+1, pai+n+1);
    for(int i = 1; i <= n; i++){
        ans = (ans*pai[i].l+pai[i].r)%mod;
    }
    cout << ans << endl;
}

507Lusir的游戏

题目描述

Lusir 正在玩一个古老的基于 DOS 的游戏。

游戏中有 N+1 座建筑——从 0 到 N 编号,从左到右排列。编号为 0 的建筑高度为 0 个单位,编号为 i 的建筑高度为 H(i) 个单位。 起初,Lusir 在编号为 0 的建筑处。每一步,它跳到下一个(右边)建筑。假设 Lusir 在第 k 个建筑,且它现在的能量值是 E,下一步它将跳到第 k+1 个建筑。

如果 H ( k + 1 ) > E H(k+1)>E H(k+1)>E,那么 Lusir 就失去 H ( k + 1 ) − E H(k+1)−E H(k+1)E 的能量值,否则他将得到 E − H ( k + 1 ) E−H(k+1) EH(k+1) 的能量值。

游戏目标是到达第 N 个建筑,在这个过程中能量值不能为负数个单位。

现在的问题是 Lusir 至少以多少能量值开始游戏,才可以保证成功完成游戏?

输入格式

第一行输入整数 N。 第二行是 N 个空格分隔的整数, H ( 1 ) , H ( 2 ) , … , H ( N ) H(1),H(2),…,H(N) H(1),H(2),,H(N) 代表建筑物的高度。

输出格式

输出一个整数,表示所需的最少单位的初始能量值上取整后的结果。

数据范围

1 ≤ N , H ( i ) ≤ 1 0 5 1≤N,H(i)≤10^5 1N,H(i)105

输入样例1

5
3 4 3 2 4

输出样例1

4

思路

二分,找最小的最大

代码

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e5+5;
int n;
int h[Max];
int maxx;
bool check(int x){
    for(int i = 1; i <= n; i++){
        x = 2*x-h[i];
        if(x < 0)  return false;
        if(x >= maxx)  return true;
    }
    return true;
}
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> h[i];
        maxx = max(maxx,h[i]);
    }
    int l = 0, r = maxx+1;
    int mid;
    while(l<r){
        mid = (l+r)/2;
        if(check(mid)) r = mid;
        else  l = mid+1;
    }
    cout << l << endl;
}

601BFS练习1

题目描述

给你一个数字a,每次可以选择下面四种操作中的一种:

把数字a加上一。
把数字a乘以2。
把数字a乘以3。
把数字a减去一。
问把这个a变成b最少需要多少步。

你要回答q个询问, b 1 , b 2 , … , b q b_1,b_2,…,b_q b1,b2,,bq,输出把a变成 b 1 , b 2 , … , b q b_1,b_2,…,b_q b1,b2,,bq的最小步数。

输入格式

第一行两个整数a,q。

接下来一行q个整数 b 1 , … , b q b_1,…,b_q b1,,bq

输入格式

输出q个数字,分别表示把a变成 b 1 , b 2 … , b q b_1,b_2…,b_q b1,b2,bq的最小步数。

样例输入

3 10
1 2 3 4 5 6 7 8 9 10

样例输出

2 1 0 1 2 1 2 2 1 2
数据规模

对于所有数据,保证 1 ≤ a , q , b i ≤ 1 0 5 1≤a,q,b_i≤10^5 1a,q,bi105

思路

对1~1e5的数据预处理,队列+bfs
把a变成b,四种操作,到达没走过的b,则赋值步数
否则不做处理

代码

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e5+5;
int a, q, b;
int f[Max];
queue<pair<int, int> > que;
int main() {
	memset(f, -1, sizeof(f));
	cin >> a >> q;
    que.push(make_pair(a,0));
	while (!que.empty()) {
		auto fro = que.front();
		que.pop();
		if(f[fro.first] == -1)  f[fro.first] = fro.second;
		if(fro.first+1 <= Max && f[fro.first+1] == -1) que.push(make_pair(fro.first+1, fro.second+1));
		if(fro.first-1 > 0 && f[fro.first-1] == -1) que.push(make_pair(fro.first-1, fro.second+1));
		if(2*fro.first <= Max && f[2*fro.first] == -1) que.push(make_pair(2*fro.first, fro.second+1));
		if(3*fro.first <= Max && f[3*fro.first] == -1) que.push(make_pair(3*fro.first, fro.second+1));
	}
	for (int i = 0; i < q; i++) {
		cin >> b;
		cout << f[b] << " ";
	}
	return 0;
}

60201序列2

题目描述

又是大家最喜欢的01序列问题了呢

这次的问题非常的简单,cc觉得一个01序列中两个1之间至少要有k个0,现在他要构造出一个长度为n的01序列,请问他有多少种不同的构造方法

这个数字可能会非常大,请你对 1 0 9 + 7 10^9+7 109+7取模

输入格式

一行,给出两个整数n,k

输出格式

一个整数,代表不同的构造方法数

数据范围

1 ≤ n ≤ 1 0 6 1≤n≤10^6 1n106
0 ≤ k < n 0≤k<n 0k<n

样例输入

4 2

样例输出

6

思路

参考自一位大佬
动态转移DP
dp[i]表示序列第i个数为1时序列前i个数的构造方法数。
状态转移:dp[i]=dp[1]+dp[2]+……+dp[i-k-1]+1

代码

#include<bits/stdc++.h> 
using namespace std;
const int Max = 1e6+5;
const long long mod = 1e9+7;
int n,k;
long long dp[Max];
long long ans[Max];
int main(){
	cin>>n>>k;
	for(int i=1; i <= n; i++){
		if(i-k-1 > 0)  dp[i]= (ans[i-k-1]+1)%mod;
		else dp[i]=1;
		ans[i]=(ans[i-1]+dp[i])%mod;
	}
	
	cout<<ans[n]+1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是夕颜呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值