T1:RSA
评析:先判断质数,然后分别分解因数,找到相同的就是no credit,否则partical credit,要注意的是可能是两个数各含有相同因数,也有可能这个数自己含有相同因数。
#include<bits/stdc++.h>
using namespace std;
long long a,b,flag1,flag2,flag3,num1[100],num2[100],t1,t2;
int main()
{
cin>>a>>b;
for (int i=2;i<=sqrt(a);i++)
{
if (a % i==0) flag1=1;
}
for (int i=2;i<=sqrt(b);i++)
{
if (b % i==0) flag2=1;
}
if (flag1==0 && flag2==0 && a!=b)
{
cout<<"full credit";
return 0;
}
if (a==b)
{
cout<<"no credit";
return 0;
}
int x=2,y=2;
while(a>1)
{
if (a % x==0)
{
a=a/x;
num1[++t1]=x;
num1[++t1]=a;
if ((a)%x==0) x--;
}
if (x>sqrt(a)) break;
x++;
}
while(b>1)
{
if (b % y==0)
{
b=b/y;
num2[++t2]=y;
num2[++t2]=b;
if ((b)%y==0) y--;
}
if (y>sqrt(b)) break;
y++;
}
sort(num1+1,num1+t1+1);
sort(num2+1,num2+t2+1);
for (int i=1;i<=t1;i++)
{
for (int j=1;j<=t2;j++)
{
if (num1[i]==num2[j] || num1[i]==num1[i+1] || num2[j]==num2[j+1])
{
flag3=1;
break;
}
}
//cout<<flag3<<endl;
}
for (int i=1;i<=t1;i++)
if (num1[i]==num1[i+1])
{
flag3=1;
break;
}
for (int j=1;j<=t2;j++)
{
if (num2[j]==num2[j+1])
{
flag3=1;
break;
}
}
if (flag3==1)
{
cout<<"no credit";
}
else cout<<"partial credit";
}
T2:数组操作
#include<bits/stdc++.h>
using namespace std;
int t,n;
int main()
{
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
scanf("%d",&n);
int a[n+5];
for (int j=1;j<=n;j++) scanf("%d",&a[j]);
int num=a[n],sum=1,ans=0;
a[0]=num;
for (int j=n;j>1;j--)
{
if (a[j]==num && a[j-1]!=num)
{
ans++;
j-=sum;
a[j]=num;
sum*=2;
j++;
}
else sum++;
}
printf("%d\n",ans);
}
}
T3:A-B数对
评析:显然O2的复杂度不行,那么直接存数组,用空间换时间。
#include<bits/stdc++.h>
using namespace std;
int n,c,a[200005],f[10000000],ans;
int main()
{
cin>>n>>c;
for (int i=1;i<=n;i++)
{
cin>>a[i];
f[a[i]+c]++;
}
for (int i=1;i<=n;i++) ans+=f[a[i]];
cout<<ans;
}
T4:数位计算
评析:本质上是等差数列求和,只要将这题巨大的数据取模处理即可。
#include <bits/stdc++.h>
using namespace std;
int n,m,t;
unsigned long long ten[19]={0};
long long pl(long long x,int len)
{
long long n=x-ten[len-1]+1;
if(len==1)
{
return n*(n+1)/2;
}
return ((n % 998244353)*((n+1) % 998244353)/2 % 998244353 + pl(ten[len-1]-1,len-1)) % 998244353;
}
int main()
{
long long x,y;
int len=0;
ten[0]=1;
for(unsigned long long i=1,j=10;i<=18;i++,j*=10)
{
ten[i]=j;
}
cin>>x;
y=x;
while(y!=0)
{
len++;
y/=10;
}
cout<<pl(x,len);
}
T5:新国王游戏
#include<bits/stdc++.h>
using namespace std;
unsigned long long ans,n,ad[1000005];
const int MOD=1000000007;
struct node
{
unsigned long long a,b;
}p[1000005];
bool cmp(node x,node y)
{
return x.b*(y.a-1)>y.b*(x.a-1);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld%lld",&p[i].a,&p[i].b);
sort(p+1,p+n+1,cmp);
ad[n]=1;
for (int i=n-1;i>=1;i--)
{
ad[i]=ad[i+1]*p[i+1].a % MOD;
}
for (int i=1;i<=n;i++)
{
ans+=ad[i]*p[i].b % MOD;
ans %= MOD;
}
printf("%lld",ans%MOD);
}
T6:完美数
评析:借鉴了一下大佬才知道思路。
- 由于数据量过大,需不断取模,而取模与除法相矛盾,我们就需要将除法变为乘法
- 而n!=n(n-1)!,(n-1)!的逆元=n!的逆元n,我们只需先求出n!,再求n!的逆元,然后递推出i!的逆元,再求n(n-1)…(n-m+1),即可求出取模后的排列组合数
- 我们还发现找逆元需要用到快速幂,我们知道21000=4500,而$3^9=3^83=9^43$
也就是说,对于一个幂,当指数为偶数时,偶数减半,底数平方,当指数为奇数时,指数-1后再减半,底数平方,用于计算最终值的1*底数,在计算的时候同时取模,就可以快速求出幂 - 具体只能尽量记一下模板吧
#include<bits/stdc++.h>
using namespace std;
const int max_m = 1e6;
const int mod_num = 1e9 + 7;
int a, b, m;
long long factorial[max_m + 1];
bool judge(int sum) {
int t = 0;
while (sum) {
t = sum % 10;
sum /= 10;
if (!(t == a || t == b)) return false;
}
return true;
}
long long pow(long long x, long long y, long long p) {
long long ret = 1;
while (y) {
if (y & 1) ret = ret * x % p;
x = x * x % p;
y >>= 1;
}
return ret;
}
long long inv(long long x, long long p) {
return pow(x, p - 2, p);
}
long long cmp(long long m, long long n) {
return factorial[n] * inv(factorial[m], mod_num) % mod_num * inv(factorial[n - m], mod_num) % mod_num;
}
int main() {
factorial[0] = 1;
for (int i = 1; i <= max_m; i++)
factorial[i] = (factorial[i - 1] * i) % mod_num;
cin >> a >> b >> m;
long long ans = 0;
for (int i = 0; i <= m; i++) {
int sum = a * i + b * (m - i);
if (judge(sum)) ans = (ans + cmp(i, m)) % mod_num;
}
cout << ans << endl;
return 0;
}
T7:Lusir的游戏
评析:二分,不算难,要注意到超过最大高度是e必然是行的,所以要找到最大高度,同时不管e是大于还是小于高度,公式都是e=2*e-a[i],那就省的判断了
#include<bits/stdc++.h>
using namespace std;
int x,n,a[100005];
int check(int e)
{
for (int i=1;i<=n;i++)
{
e=2*e-a[i];
if (e<0) return 0;
else if (e>x) return 1;
}
return 1;
}
int main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i];
x=max(a[i],x);
}
int l=0,r=1e9,mid;
while(l<r)
{
mid=(l+r)/2;
if (check(mid)) r=mid;
else l=mid+1;
}
cout<<l;
}
T8:BFS练习1
评析:BFS模板题,但要注意用vis数组标记,以及不用变时的那个a要清零
#include<bits/stdc++.h>
using namespace std;
queue<int>q;
int a,q1,b,vis[100005],ans[100005];
void bfs(int x)
{
//memset(ans,-1,sizeof(ans));
//ans[a]=0;
q.push(a);
while(q.size())
{
int t=q.front();q.pop();
if (t+1>=1 && t+1<=100000 && vis[t+1]==0)
{
q.push(t+1);
vis[t+1]=1;
ans[t+1]=ans[t]+1;
}
if (t-1>=1 && t-1<=100000 && vis[t-1]==0)
{
q.push(t-1);
vis[t-1]=1;
ans[t-1]=ans[t]+1;
}
if (t*2>=1 && t*2<=100000 && vis[t*2]==0)
{
q.push(t*2);
vis[t*2]=1;
ans[t*2]=ans[t]+1;
}
if (t*3>=1 && t*3<=100000 && vis[t*3]==0)
{
q.push(t*3);
vis[t*3]=1;
ans[t*3]=ans[t]+1;
}
}
ans[a]=0;
}
int main()
{
cin>>a>>q1;
bfs(a);
for (int i=1;i<=q1;i++)
{
cin>>b;
cout<<ans[b]<<" ";
}
}
T9:01序列2
评析:又是组合数+快速幂,真是头痛
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mode 1000000007
#define N 1000005
ll qpow(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)
{
ans = ans * a % mode;
}
a = a * a % mode;
b >>= 1;
}
return ans;
}
ll f[N], nif[N];
ll C(ll a, ll b)
{
return (f[a] * nif[b] % mode * nif[a - b] % mode) % mode;
}
ll n, k;
int main()
{
cin >> n >> k;
ll ans = 0;
f[0] = 1;
nif[0] = 1;
for (ll i = 1; i < N; i++)
{
f[i] = i * f[i - 1] % mode;
}
nif[N - 1] = qpow(f[N - 1], mode - 2);
for (ll i = N - 2; i >= 1; i--)
{
nif[i] = nif[i + 1] * (i + 1) % mode;
}
ll cnt = -1;
while (1)
{
cnt++;
ll x = cnt + (cnt - 1) * k;
if ( x > n)break;
if (cnt == 0)
{
ans++;
continue;
}
if (cnt == 1)
{
ans += n;
continue;
}
ans = (ans + C(n - x+cnt, cnt))%mode;
}
cout << ans%mode << endl;
return 0;
}
T10:整除光棍
评析:事实上是对除法竖式的模拟,我们可以在纸上画一画找找感觉,很显然这题数据量很大,我们要是直接暴力字符串会比较麻烦,但是模拟除法相当于一位一位的去算,大大降低计算量。所以先找到比x大的最小的a,然后一位位落下来往后算即可。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int x,num=0;
cin>>x;
int a=1;
while(x>a)
{
a=a*10+1;
num++;
}
while(1)
{
cout<<(a/x);
a=a % x;
if (a==0) break;
a=a*10+1;
num++;
}
cout<<" "<<(num+1);
}