真想再体验一把新生杯。(部分题解)
Problem A: Chinese Remainder Theorem
思路:中国剩余定理,套个板子就行了,注意输入的数据要去重。# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
const int maxn = 20;
int n;
LL m[maxn], r[maxn];
int vis[20][20];
LL extend_Euclid(LL a, LL b, LL &x, LL &y)//扩展欧几里得。
{
if(b==0)
{
x = 1; y = 0;
return a;
}
LL r = extend_Euclid(b, a%b, y, x);
y -= a/b*x;
return r;
}
LL China()
{
LL M = 1, ans = 0;
for (int i = 0; i < n; ++i) M *= m[i];
for(int i = 0;i < n;i++)
{
LL N = M/m[i];
LL x, y;
extend_Euclid(N, m[i], x, y);
x = (x%m[i] + m[i]) % m[i];
ans = ((ans+r[i]*N%M*x%M)%M + M) % M ;
}
return (M+ans%M)%M;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int i,cnt=0;
memset(vis, 0, sizeof(vis));
for(i=0; i<n; ++i)
{
LL tx, ty;
scanf("%lld%lld",&tx,&ty);
if(!vis[tx][ty] == 1)
{
vis[tx][ty] = 1;
r[cnt] = tx;
m[cnt++] = ty;
}
}
n = cnt;
LL ans = China(), f=1;
for(int i=0; i<n; ++i)
{
if(ans%m[i] != r[i])
{
f = 0;
puts("IMPOSSIBLE");
break;
}
}
if(f) printf("%lld\n",ans);
}
return 0;
}
Problem B: AC的概率
思路:根据同余定理,(a+b)%6==0,有(a%6+b%6)%6 == 0,将每个数先取模6,同时记录到数组b上,扫一遍即可。# include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+30;
int a[maxn];
int main()
{
int t, n;
scanf("%d",&t);
while(t--)
{
int b[7]={0};
scanf("%d",&n);
double tot = (double)n*(n-1)/2, sum=0;
for(int i=0; i<n; ++i)
{
scanf("%d",&a[i]);
a[i] %= 6;
if(a[i] == 0) sum += b[a[i]];
else sum += b[6-a[i]];
++b[a[i]];
}
printf("%.6f\n",sum*1.0/tot);
}
return 0;
}
Problem D: 好难啊
思路:目测是CF Div2的一道题,先不考虑最后一行和最后一列,任意填充前(n-1)*(m-1)个格,那么最后一行和最后一列显然可以填上1或-1使得每行每列都等于k,那么右下角那个格子呢?设前(n-1)*(m-1)个格乘积为sum,对于列来说,右下角填上A=k^(n-1)*sum,对于行来说右下角填上B=k^(m-1)*sum。那么显然如果k=-1,且n和m奇偶性不同时A不等于B,其余情况都能满足。# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
typedef long long LL;
int main()
{
LL n, m, k;
while(~scanf("%lld%lld%lld",&n,&m,&k))
{
if((n&1) != (m&1) && k == -1)
puts("Orz");
else puts("O(^_^)O~~");
}
return 0;
}
Problem E: 工会首领yjl
思路:贪心,先按Q值排序,所有人得到ceil(Q/2)元,剩下的钱倒着派发,Q值大的先派发。# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
typedef long long LL;
struct node
{
int x, id;
}a[103];
int ans[103];
bool cmp(node a, node b)
{
return a.x < b.x;
}
int main()
{
int n, m;
while(~scanf("%d%d",&n,&m))
{
for(int i=0; i<n; ++i)
{
scanf("%d",&a[i].x);
a[i].id = i;
}
sort(a, a+n, cmp);
int sum = 0, sum2=0;
for(int i=0; i<n; ++i)
{
int tmp = (int)ceil(a[i].x/2.0);
ans[a[i].id] = tmp;
sum += tmp;
sum2 += a[i].x;
}
if(sum > m || sum2 < m)
{
puts("gg");
continue;
}
int rest = m-sum;
for(int i=n-1; i>=0; --i)
{
int id = a[i].id;
int imin = min(rest, a[i].x-ans[id]);
if(i < n-1) imin = min(imin, ans[a[i+1].id]-ans[id]);
ans[id] += imin;
rest -= imin;
}
for(int i=0; i<n; ++i)
printf("%d ",ans[i]);
puts("");
}
return 0;
}
Problem F: 位数是多少?
思路:计算一个数x的位数是log10(x)+1,计算log10(a^b)+1可以化为b*log10(a)+1。# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
typedef long long LL;
using namespace std;
int main()
{
int x, y, t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&x,&y);
printf("%d\n",(int)(y*log10(x))+1);
}
return 0;
}
Problem G: 一道简单的题目
思路:就是直接做,但是数据我故意加了一堆1进去...所以预处理每个1右边的首个非1数的位置即可,不然会超时。
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int maxn = 1e5+30;
int a[maxn], r[maxn];
int main()
{
int n, q, L, R, K;
while(~scanf("%d%d",&n,&q))
{
memset(r, 0, sizeof(r));
memset(a, 0, sizeof(a));
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
r[n] = n+1;
for(int i=n-1; i>=1; --i)
{
if(a[i+1] == 1) r[i] = r[i+1];
else r[i] = i+1;
}
while(q--)
{
scanf("%d%d%d",&L,&R,&K);
for(int i=L; i<=R; i=r[i])
{
K /= a[i];
if(K==0) break;
}
printf("%d\n",K);
}
}
return 0;
}
Problem H: 一棵二叉树
思路:子节点除以二就是父节点的编号,一直往上除直到一存到数组。比较两个点的公共祖先最大那个。#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
LL arr[500];
int main()
{
int T;
LL a,b;
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&a,&b);
memset(arr,0,sizeof(arr));
int tmp=0;
while(a){
arr[tmp++]=a;
a>>=1;
}
while(b){
arr[tmp++]=b;
b>>=1;
}
sort(arr,arr+tmp);
for(int i=tmp-1;i;--i)
if(arr[i]==arr[i-1]){
printf("%lld\n",arr[i]);
break;
}
}
return 0;
}
后面的先留坑