题目链接:https://ac.nowcoder.com/acm/contest/5674#question
A-Groundhog and 2-Power Representation
题意
- 求表达式的值
- 只有2 0 + ( ) 组成
- 2(0)表示2的0次
思路
- 用python写非常方便
- 写个x(i)函数表示2的幂次,然后将字符串中的"2("字符替换成"x("
- 最后调用eval函数将字符串变成有效的表达式求值并返回结果
AC代码
def x(i):
return 2**i
str = input()
str = str.replace("2(","x(")
print(eval(str))
E-Groundhog Chasing Death
题意
- 求
mod 998244353的结果
思路
- 唯一分解定理:任何数都可以表示成质因子幂次相乘的形式。
,
- gcd(n,m)=
- 因为
,所以设p是n,m共有的质因子,k1和k2是n,m对于p的幂次,则就是求解
(p是n,m共有的质因子)
- 优化一个for,找到k1*i和k2*j的零界点sh,sh=k1*i/k2,此时j在sh左边的时候,min总是取k1*i,由于此时的i不变,直接乘数量就好了;j在sh右边的时候,min总是取k2*j,由于j在变,不过就是对等差数列求和。
- 数规模会很大,取模太多又感觉很烦,其他人是通过欧拉降幂优化,我门就很莽,直接__int128冲,最后取模!!
AC代码
#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
#define ll __int128
using namespace std;
const ll mod = 998244353;
inline void print(__int128 x)
{
if (x < 0)
{
x = -x;
putchar('-');
}
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
template <typename _Tp>
inline void read(_Tp &x)
{
char ch;
bool flag = 0;
x = 0;
while (ch = getchar(), !isdigit(ch))
if (ch == '-')
flag = 1;
while (isdigit(ch))
x = x * 10 + ch - '0', ch = getchar();
if (flag)
x = -x;
}
inline ll POW(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
map<ll, ll> num1; //存放x质因子和需要幂的数ai
map<ll, ll> num2; //存放y质因子和需要幂的数bi
map<ll, ll> ans; //共同质因子和需要幂的数
int main()
{
ll a, b, c, d, x, y;
read(a);
read(b);
read(c);
read(d);
read(x);
read(y);
for (ll i = 2; i * i <= x; i++) //x质因子分解
if (x % i == 0)
{
int cnt = 0;
while (x % i == 0)
cnt++, x /= i;
num1[i] = cnt;
}
if (x != 1)
num1[x] = 1;
for (ll i = 2; i * i <= y; i++) //y质因子分解
if (y % i == 0)
{
int cnt = 0;
while (y % i == 0)
cnt++, y /= i;
num2[i] = cnt;
}
if (y != 1)
num2[y] = 1;
for (auto p : num1)
{
if (!num2[p.first])
continue;
ll pi = p.first, k1 = p.second, k2 = num2[pi];
for (ll i = a; i <= b; i++)
{
ll sh = k1 * i / k2; //j从1到sh,min都是k1*i;
//j大于sh,min都是k2*j
if (sh < c)
ans[pi] += k1 * i * (d - c + 1);
else if (sh >= d)
ans[pi] += k2 * (c + d) * (d - c + 1) / 2; //等差数列求和
else
ans[pi] += k1 * i * (d - sh) + k2 * (sh + c) * (sh - c + 1) / 2;
}
}
ll res = 1;
for (auto p : ans) //所有共同质因子幂次累乘
res = res * POW(p.first, p.second) % mod;
print(res % mod);
system("pause");
return 0;
}
F-Groundhog Looking Dowdy
题意
- 给定n天,每天生产ki件衣服,选择m件来自不同天的衣服,求最大价格和最小价格的最小差值
- 数据范围:1<=aij<=1e9,1<=n<=1e6,1<=m<=n,sum of clothes<=2e6,k>=1
思路
- 尺取法。
- 首先结构体存衣服生产日期和价格,按照价格从小到大排序。
- l,r分别是左右端点,当区间内衣服不同生产日期数num没有超过m时,r++;
- 等于m时,更新左右端点价格差值的最小值 ,l++,直到num<m。
AC代码
#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const double pi = acos(-1.0);
const int mod = 1e9 + 7;
const int maxn = 1e6+5;
const int inf = 0x3f3f3f3f;
struct node{
int val,id;
bool operator < (const node &a)const{
return val<a.val;
}
}a[maxn<<1];
int cnt[maxn];
int main(){
int n,m,len=0;
sc2(n,m);
for(int i=1;i<=n;i++){
int k,x;
sc(k);
while(k--){
sc(x);
a[++len]={x,i};
}
}
sort(a+1,a+len+1);
// cout<<"print-----------"<<endl;
// for(int i=1;i<=len;i++)cout<<a[i].id<<" ";
// cout<<endl;
// for(int i=1;i<=len;i++)cout<<a[i].val<<" ";
// cout<<endl;
int l=1,r=1,ans=inf,num=0;
while(r<=len){
if(++cnt[a[r].id]==1)num++;
if(num==m){
ans=min(ans,a[r].val-a[l].val);
while(num==m){
if(--cnt[a[l++].id]==0)num--;
}
}r++;
//cout<<"ans:::"<<ans<<endl;
}
cout<<ans<<endl;
system("pause");
return 0;
}
由于数据给的弱,以下代码可以水过去,要不是敲得慢,差点拿一血QAQ
#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const int maxn = 2e5+5;
const int inf = 0x3f3f3f3f;
int main(){
int n,m;
sc2(n,m);
vector<int>v;
while(n--){
int k,x,mii=inf;sc(k);
while(k--){
sc(x);
mii=min(mii,x);
}
v.push_back(mii);//每天取最便宜的
}
sort(v.begin(),v.end());//从小到大排
cout<<v[m-1]-v[0]<<endl;//最小的m个左右差值
system("pause");
return 0;
}
I-The Crime-solving Plan of Groundhog
题意
- 给一个序列仅包含数字,让你将其打乱次序并组合成两部分,使这两部分组成的数字相乘得到的结果最小
- 不允许任何一部分组成的数字包含前导零
思路
- 大数运算。 两位乘两位的数字一定比一位乘三位的数字大。证明过程如下:
- (10a+d)*(10b+c)=100ab+10ac+10bd+cd
- (100b+10c+d)*a=100ab+10ac+ad<(10a+d)*(10b+c)
- 组合成1位数乘n-1位数
- 1位数是除零外最小的
- n-1位数是第一位是除零最小,接着是从小到大加入
- 然后是模拟乘法运算。
AC代码
#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const int maxn = 1e5+5;
int cnt[maxn],a[maxn];
int main(){
int t;sc(t);
while(t--){
int n,x;sc(n);
mem(cnt,0);//数组清零
for(int i=1;i<=n;i++){
sc(x);
cnt[x]++;
}
int bas=0,ca=0;
for(int i=1;i<10;i++){//找第一个非零
if(cnt[i]){
bas=i;
cnt[i]--;
break;
}
}
for(int i=1;i<10;i++){//找第一个非零
if(cnt[i]){
a[++ca]=i;
cnt[i]--;
break;
}
}
for(int i=0;i<10;i++){//从小到大加入
if(cnt[i]){
while(cnt[i]--){
a[++ca]=i;
}
}
}
string b;
for(int i=ca;i>=1;i--){//从个位开始乘
t+=bas*a[i];
b+=t%10+'0';//存余数
t/=10; //进位
}
if(t)b+=t+'0'; //最后进位
reverse(b.begin(),b.end());//字符串反转
cout<<b<<endl;
}
system("pause");
return 0;
}
K-The Flee Plan of Groundhog
题意
- 有n个结点,n-1条边,小A从1号结点出发前往n号结点看望小B,每秒能走一条路
- t秒钟之后小B从n结点出发,来追小A,每秒能走两条路
- 问最迟要多久才能相遇
思路
- 以n结点为根dfs递归建树。pre数组存放父节点,dep数组存放结点的深度,maxd数组存放子节点最深深度。
- n个结点,n-1条边,说明这是一棵树,所以小A从1出发去n只有一条路径,t秒之后小A的位置可以计算出来 。
- 求的是最迟相遇时间,那么小A就要远离小B,往树的深处跑,那么就有两种情况。
- 第一种情况,小A还没到树的最深处就被小B追上了。因为小B速度是小A的两倍,那么追逐时间其实就是两人的深度之差。
- 第二种情况,小A到最深处等小B。那么追逐时间就是小B到达最深处的时间。
AC代码
#include <bits/stdc++.h>
#define LL long long
#define sc(a) scanf("%d", &a)
#define sc2(a, b) scanf("%d%d", &a, &b)
#define sc3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define scl(a) scanf("%lld", &a)
#define scl2(a, b) scanf("%lld%lld", &a, &b)
#define ss(a) scanf("%s", a)
#define mem(a, b) memset(a, b, sizeof(a))
#define PII pair<int, int>
using namespace std;
const int maxn = 1e5+5;
vector<int>v[maxn];
int pre[maxn],dep[maxn],maxd[maxn];
void add(int a,int b){
v[a].push_back(b);
v[b].push_back(a);
}
void dfs(int s,int fa){ //dfs建树
for(auto i:v[s]){ //遍历子树
if(i==fa)continue; //不必跑父节点
pre[i]=s; //存放父节点
dep[i]=dep[s]+1; //子节点的深度等于父节点深度加1
maxd[i]=dep[i]; //存放子节点最深深度
dfs(i,s); //向下递归
maxd[s]=max(maxd[s],maxd[i]);//递归到根节点时,从下到上更新子节点最深深度
}
}
int main(){
int n,t;
sc2(n,t);
for(int i=1;i<n;i++){
int x,y;
sc2(x,y);
add(x,y);
}
dep[n]=0;//根节点深度为0
dfs(n,-1);
int p=1;
while(t--){//小A先走t秒
if(p==n)break;
p=pre[p];
}
//dep[p]就是第一种情况
//(maxd[p]+1)/2就是第二种情况
cout<<min(dep[p],(maxd[p]+1)/2)<<endl;
system("pause");
return 0;
}