RSA
RSA算法选择两个不同质数的积作为模数。现在有两个正整数 A,B,如果它们是不同的质数,则判定为 full credit
;否则,如果A⋅B不是任意大于11的整数的平方的整数倍,则判定 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≤10^12。
#include<bits/stdc++.h>
using namespace std;
long long a,b,ans;
vector<long long>m;
void d(long long x)
{
long long t=2;
while(t<=x/t)
{
if(x%t==0&&t>1)
{
//cout<<t<<" "<<x/t<<"->"<<x<<endl;
auto l=find(m.begin(),m.end(),t);
if(l==m.end())m.push_back(t);
else
{
ans=1;
m.erase(l);
return ;
}
if(t!=x/t)
{
l=find(m.begin(),m.end(),x/t);
if(l==m.end())m.push_back(x/t);
else
{
ans=1;
m.erase(l);
return ;
}
}
else
{
ans=1;
return ;
}
}
t++;
}
auto l=find(m.begin(),m.end(),x);
if(l==m.end())m.push_back(x);
else
{
ans=1;
m.erase(l);
return ;
}
// for(int i=0;i<m.size();i++)cout<<m[i]<<" ";
//cout<<endl;
}
int main()
{
cin>>a>>b;
if(a==b)cout<<"no credit\n";
else
{
d(a);
if(!ans)d(b);
if(ans)cout<<"no credit\n";
else if(m[0]==a&&m[1]==b)cout<<"full credit\n";
else cout<<"partial credit\n";
}
}
数组操作
给你一个有 n 个元素的数组 a 。你可以对它进行如下操作,次数不限。
从一个偶数大小为 2k的数组中选择一些从位置 l 开始的子数组(1≤l≤l+2⋅k−1≤n, k≥1) ,对于 0 到 k−1(包括)之间的每一个 i ,将值 al+k+i分配给 al+i 。
例如,如果 a=[2,1,3,4,5,3] ,然后选择 l=1和 k=2 ,应用这个操作,数组将变成 a=[3,4,3,4,5,3]。
请找出使数组中所有元素相等所需的最少操作数(可能是零)。
输入格式
输入由多个测试用例组成。第一行输入一个整数 t(1≤t≤2×104)表示测试用例的数量。
每个测试用例的包含 (n+1)个整数:
第一个整数 n(1≤n≤2×105)表示数组的长度。
此后 n 个整数 a1,a2,...,an(1≤ai≤n) 表示数组的元素。
输出格式
输出 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 之和不超过 200000200000。
提示
在第一个测试中,所有元素都是相等的,因此不需要任何操作。
在第二个测试中,你可以应用一个操作,k=1,l=1,设置 a1←a2 ,通过 1 个操作,数组变成 [1,1][1,1]。
在第三个测试中,你可以应用一个操作,k=1,l=4,设置 a4←a5,然后数组变成 [4,4,4,4,4]。
在第四个测试中,你可以应用一个操作,k=1,l=3,设置 a3←a4 ,数组变成 [4,2,3,3],然后你可以应用另一个操作,k=2,l=1,设置 a1←a3,a2←a4,, 数组变成 [3,3,3,3]。
在第五次测试中,只有一个元素,因此不需要任何操作。
#include<bits/stdc++.h>
using namespace std;
int a[200005],n,t;
int main()
{
cin>>t;
for(int i=1;i<=t;i++)
{
scanf("%d",&n);
int f=0;
for(int j=1;j<=n;j++)
{
scanf("%d",&a[j]);
if(j>1&&a[j]!=a[j-1])f=1;
}
int e=a[n],l=1,j=n-1,ans=0;
if(f==0)
{
ans++;
l=n;
}
while(l!=n)
{
l=1,j=n-1;
while(a[j]==e&&j>0)
{
l++;
j--;
}
j++;
for(int k=n-l;k>=max(1,n-2*l+1);k--)a[k]=e;
ans++;
}
ans--;
printf("%d\n",ans);
}
}
#616. A-B 数对
给出一串数以及一个数字 C ,要求计算出所有 A−B=C的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入格式
输入共两行。
第一行,两个整数 N, C。
第二行, N个整数,作为要求处理的那串数。
输出格式
一行,表示该串数中包含的满足 A−B=C 的数对的个数。
样例输入
4 1
1 1 2 3
样例输出
3
数据范围
1≤N≤2×10^5, 1≤C≤2×10^5, 题目保证输入的 N 个数范围小于 2^30。
#include<bits/stdc++.h>
using namespace std;
int N[200005],n,c,ans;
int main()
{
cin>>n>>c;
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
N[a]++;
}
for(int i=1;i<=200005-c;i++)
{
ans+=N[i+c]*N[i];
}
cout<<ans;
}
#666. 数位计算
给出一个整数 n,请解决下面的问题:
使 f(x)=(不超过 x 且与 x 具有相同位数的正整数的个数)。
求出 f(1)+f(2)+...+f(n),结果对 998244353 取模。
输入格式
一个整数 N。
输出格式
一个整数——上面问题的答案,并对 998244353 取模。
样例输入1
16
样例输出1
73
样例解释:对从 1 到 9 的每个 x,不超过 x 且与 x具有相同位数的正整数有 1,2,..,x,因此,f(1)=1,f(2)=2,...,f(9)=9。对从 10 到 16 的每个 x,不超过 x 且与 x 具有相同位数的正整数有 10,11,..,x,因此,f(10)=1,f(11)=2,...,f(16)=7。所以答案为 73。
样例输入2
238
样例输出2
13870
样例输入3
999999999999999999
样例输出3
762062362
数据规模
所有数据保证 1≤N<10^18,且 N 是整数。
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
unsigned long long n,ans,t=1;
int main()
{
cin>>n;
for(int i=1;i<=18;i++)
{
if(n/t==0)break;
t*=10;
unsigned long long a=n%t,add;
if(n/t==0)
{
add=(((((a-(t/10)+2)%mod)*(a>=10?(a-(t/10)+1):a)%mod))/2)%mod;
// cout<<(a-(t/10)+2)<<"*"<<(a>=10?(a-(t/10)+1):a)<<"/2";
}
else
{
// cout<<"-++-\n";
add=(((((t-1)-(t/10)+2)%mod)*(((t-1)>=10?((t-1)-(t/10)+1):(t-1))%mod))/2)%mod;
// cout<<((t-1)-(t/10)+2)<<"*"<<((t-1)>=10?((t-1)-(t/10)+1):(t-1))<<"/2";
}
ans=(ans+add)%mod;
// cout<<'+'<<add<<endl;
}
cout<<ans;
}
#672. 新国王游戏
又到了 H 国国庆, 国王再次邀请 n 位大臣来玩有奖游戏。上次国庆被众臣吐槽国王小气后,国王决定今年大方点,改变游戏规则且不再参与游戏,免得被大臣们质疑。首先, 他让每位大臣在左、 右手上面分别写下一个正整数。然后让这 n位大臣排成一排。排好队后, 所有的大臣都会获得国王奖赏的若千金币, 每位大臣获得的金币数分别是:排在该大臣后面的所有人的左手上的数的乘积乘以他自己右手上的数。国王希望所有大臣获得的金币数之和最多,所以他想请你帮他重新安排一下队伍的顺序。
简而言之,给定 n对数 ai,bi,找到一种排列顺序,使得 b1×a2∗a3∗…an+b2×a3∗a4∗…an+⋯+bn 最大,求最大值,由于答案可能很大,需要对 1000000007 取模
输入格式:
第一行,包含一个整数 n。 第二行到第 n+1行,包含两个整数 ai,bi
输出格式:
输出一行,表示按某种排序后的 b1×a2∗a3∗…an+b2×a3∗a4∗…an+⋯+bn的最大值对 1000000007取模的结果
样例输入
2
1 2
3 4
样例输出
10
说明
只有两种情况:
1.
1 2
3 4
(2∗3)+4=10(2∗3)+4=10
2.
3 4
1 2
(4∗1)+2=6(4∗1)+2=6
所以答案为 10
数据限制
对于 100% 的数据,保证 1≤n≤10^6,1≤ai,bi≤2^30
#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
long long n,t=1,sum;
struct aaa
{
long long a,b;
}s[1000005];
bool cmp(aaa m,aaa n)
{
return (m.b*n.a+n.b)>(n.b*m.a+m.b);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>s[i].a>>s[i].b;
sort(s+1,s+1+n,cmp);
for(int i=n;i>=1;i--)
{
int N=(t*s[i].b)%mod;
// cout<<N<<endl;
t=(t*s[i].a)%mod;
sum=(sum+N)%mod;
}
cout<<sum;
}
#669. 完美数
对于给定的数字 a , b ,当整数 n 在十进制下的所有数位都为 a 或 b时,我们称 n 是“好数”
对于好数 n ,当 n在十进制下每一位的数字之和也为“好数”时,我们称 n是一个“完美数”
请你求出有多少 m位数是“完美数”
输入格式
输入一行三个整数 a , b , m , 含义如题面所示 (1≤m≤10^6,1≤a,b≤9)。
输出格式
输出一行一个整数表示完美数的数量 , 由于答案可能很大 , 请你将答案对 10^9+7 取模
样例输入
5 1 5
样例输出
1
样例解释
只有 11111 满足要求
#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
long long a,b,m,sum,t,x[1000005];
long long qmi(long long a,long long b)
{
long long res=1;
while (b)
{
if(b&1)res=res*a%mod;
a=a*(long long)a%mod;
b>>=1;
}
return res;
}
long long C(int p,int q)
{
return (x[p]*qmi(x[p-q],mod-2)%mod*qmi(x[q],mod-2))%mod;
}
int main()
{
cin>>a>>b>>m;
long long t=1;
for(int i=1;i<=m;i++)
{
t=(t*i)%mod;
x[i]=t;
}
x[0]=1;
for(int i=0;i<=m;i++)
{
int f=0;
t=a*i+b*(m-i);
int aaa=t;
// cout<<t<<endl;
while(t)
{
int d=t%10;
if(d!=a&&d!=b)
{
f=1;
break;
}
t/=10;
}
if(f==0)
{
// cout<<aaa<<"C"<<i<<"="<<C(m,i)<<endl;
sum=(sum+C(m,i))%mod;
}
}
cout<<sum;
}
#674. Lusir的游戏
Lusir 正在玩一个古老的基于 DOS 的游戏。
游戏中有 N+1座建筑——从 0 到 N 编号,从左到右排列。编号为 0 的建筑高度为 0 个单位,编号为 i的建筑高度为 H(i)个单位。 起初,Lusir 在编号为 0 的建筑处。每一步,它跳到下一个(右边)建筑。假设 Lusir在第 k个建筑,且它现在的能量值是 E,下一步它将跳到第 k+1个建筑。
如果 H(k+1)>E,那么 Lusir就失去 H(k+1)−E 的能量值,否则他将得到 E−H(k+1)的能量值。
游戏目标是到达第 N 个建筑,在这个过程中能量值不能为负数个单位。
现在的问题是 Lusir至少以多少能量值开始游戏,才可以保证成功完成游戏?
输入格式
第一行输入整数 N。 第二行是 N 个空格分隔的整数,H(1),H(2),…,H(N)代表建筑物的高度。
输出格式
输出一个整数,表示所需的最少单位的初始能量值上取整后的结果。
数据范围
1≤N,H(i)≤10^5
输入样例1:
5
3 4 3 2 4
输出样例1:
4
#include<bits/stdc++.h>
using namespace std;
long long N,E,a[100005],ans,m;
bool check(int e)
{
E=e;
for(int i=1;i<=N;i++)
{
E+=(E-a[i]);
if(E>=50000000)return 1;
// cout<<E<<" ";
if(E<0)return 0;
}
return 1;
}
int main()
{
cin>>N;
for(int i=1;i<=N;i++)
{
cin>>a[i];
m=max(m,a[i]);
}
int l=0,r=m;
while(l<=r)
{
// cout<<l<<" "<<r<<endl;
int mid=(l+r)/2;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
// cout<<endl;
}
cout<<ans;
}
#147. BFS练习1
给你一个数字a,每次可以选择下面四种操作中的一种:
- 把数字a加上一。
- 把数字a乘以2。
- 把数字a乘以3。
- 把数字a减去一。
问把这个a变成b最少需要多少步。
你要回答q个询问,b1,b2,…,bq,输出把a变成b1,b2,…,bq的最小步数。
输入格式
第一行两个整数a,q。
接下来一行q个整数b1,…,bq。
输入格式
输出q个数字,分别表示把a变成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,bi≤10^5。
#include<bits/stdc++.h>
using namespace std;
queue<int>q;
int a,n,b[100005],vis[100005],ans[100005],s;
int main()
{
cin>>a>>n;
for(int i=1;i<=n;i++)
{
cin>>b[i];
ans[i]=-1;
}
q.push(a);
vis[a]=1;
while(!q.empty())
{
int len=q.size(),f=1;
for(int i=1;i<=n;i++)
{
if(ans[i]==-1)
{
f=0;
break;
}
}
if(f)break;
for(int i=1;i<=len;i++)
{
int t=q.front();
// cout<<t<<" ";
if(ans[t]==-1)ans[t]=s;
q.pop();
if(t-1>=0&&t-1<=100000)
{
if(!vis[t-1])
{
q.push(t-1);
vis[t-1]=1;
}
}
if(t*3>=0&&t*3<=100000)
{
if(!vis[t*3])
{
q.push(t*3);
vis[t*3]=1;
}
}
if(t*2>=0&&t*2<=100000)
{
if(!vis[t*2])
{
q.push(t*2);
vis[t*2]=1;
}
}
if(t+1>=0&&t+1<=100000)
{
if(!vis[t+1])
{
q.push(t+1);
vis[t+1]=1;
}
}
}
// cout<<endl;
s++;
}
for(int i=1;i<=n;i++)cout<<ans[b[i]]<<" ";
}
01序列2
又是大家最喜欢的01序列问题了呢
这次的问题非常的简单,cc觉得一个01序列中两个1之间至少要有k个0,现在他要构造出一个长度为n的01序列,请问他有多少种不同的构造方法
这个数字可能会非常大,请你对10^9+7取模
输入格式
一行,给出两个整数n,k
输出格式
一个整数,代表不同的构造方法数
数据范围
1≤n≤10^6
0≤k<n
样例输入
4 2
样例输出
6
#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
long long n,k,ans=1,x[1000005];
long long qmi(long long a,long long b)
{
long long res=1;
while (b)
{
if(b&1)res=res*a%mod;
a=a*(long long)a%mod;
b>>=1;
}
return res;
}
long long C(int p,int q)
{
if(p==q)return 1;
return (x[p]*qmi(x[p-q],mod-2)%mod*qmi(x[q],mod-2))%mod;
}
int main()
{
cin>>n>>k;
long long t=1;
for(int i=1;i<=n;i++)
{
t=(t*i)%mod;
// cout<<t<<" ";
x[i]=t;
}
// cout<<"\n------------------------\n";
int i=1;
while(i<=n-(i-1)*k)
{
ans=(ans+C((n-(i-1)*k),i))%mod;
// cout<<C((n-(i-1)*k),i)<<" "<<(n-(i-1)*k)<<" "<<i<<endl;
i++;
}
cout<<ans<<endl;
}
#676. 整除光棍
这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由 11 组成的数字,比如 1、111、111、11111、111、111、1111 等。传说任何一个光棍都能被一个不以 55 结尾的奇数整除。比如, 111111111111 就可以被 1313 整除。 现在,你的程序要读入一个整数 x ,这个整数一定是奇数并且不以 5 结尾。然后,经过计算,输出两个数字:第一个数字 s,表示x 乘以 s 是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。
提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除 x 为止。但难点在于,s 可能是个非常大的数 —— 比如,程序输入 3131 ,那么就输出 3584229390681和 15 ,因为 31 乘以 3584229390681的结果是 111111111111111 ,一共 15 个 11。
输入格式
输入在一行中给出一个不以 5 结尾的正奇数 x(x<1000)。
输出格式
在一行中输出相应的最小的 s 和 n,其间以 1 个空格分隔。
样例输入
31
样例输出
3584229390681 15
#include<bits/stdc++.h>
using namespace std;
long long x,s=1,n=1;
int main()
{
cin>>x;
while(x>s)
{
s=s*10+1;
n++;
}
while(1)
{
cout<<(int)(s/x);
s%=x;
if(!s)break;
s=s*10+1;
n++;
}
cout<<" "<<n;
}