The 2021 ICPC Asia Regionals Online Contest (II)
比赛链接
The 2021 ICPC Asia Regionals Online Contest (II)
G Limit
Description
Given \(2n\) integers, \(a_1,a_2 ,…,a_n ,b_1 ,b_2 ,…,b_n\) , and an integer t. You need to calculate:
\(lim _{x→0}\frac{∑_{i=1}^na_i⋅ln(1+b_i⋅x)}{x^t}\).
Input
The first line consists of two integers n,t.
In the following n lines, the i-th line consists of two integers \(a_i ,b_i\).
\(1≤n≤100000,−100≤a_i,b_i≤100,0≤t≤5.\)
Output
Please output the result of this limit. If the result is \(∞\), please output "infinity" (without quotes). And if the result is an integer, please output this integer directly. Otherwise, the answer must be \(b,a\) , such that a and b are coprime and \(b≥2\), please output "a/b".
Sample Input 1
2 2
1 1
1 -1
Sample Output 1
-1
Sample Input 2
2 1
1 1
1 -1
Sample Output 2
0
Sample Input 3
2 3
1 1
1 -1
Sample Output 3
infinity
解题思路
洛必达法则
根据 \(t\) 值,运用洛必达法则,即:分子为0时可以使用洛必达公式,否则答案为infinity
,具体如下:t
- 时间复杂度:\(O(nt)\)
泰勒展开
直接对 \(ln(1+b_i)\) 进行泰勒展开、变形即可,如下:
依上,对于 \(j\),我们先枚举 \(1\sim t-1\),如果第二重循环的和非0,即 \(\frac{常数}{x^{t-j}}\),\(x\) 趋于 \(0\),则答案为infinity
,否则 \(j=t\) 时必有答案 \(\frac{\sum_{i=1}^na[i]*pow(-b[i],t-1)*b[i]}{t}\)
- 时间复杂度:\(O(nt)\)
代码
- 洛必达
//G:洛必达法则
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
using LL=long long;
int n,t,a[N],b[N];
LL res;
int main()
{
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
if(t==0)puts("0");
else
{
for(int i=1;i<=n;i++)
res+=a[i]*b[i];
if(t==1)
printf("%lld\n",res);
else if(res==0)
{
for(int i=1;i<=n;i++)
res+=a[i]*b[i]*b[i];
res/=(-2);
if(t==2)
printf("%lld\n",res);
else if(res==0)
{
for(int i=1;i<=n;i++)
res+=a[i]*b[i]*b[i]*b[i];
res/=3;
if(t==3)
printf("%lld\n",res);
else if(res==0)
{
for(int i=1;i<=n;i++)
res+=a[i]*b[i]*b[i]*b[i]*b[i];
res/=4;
if(t==4)
printf("%lld\n",res);
else if(res==0)
{
for(int i=1;i<=n;i++)
res+=a[i]*b[i]*b[i]*b[i]*b[i]*b[i];
printf("%lld",res/30);
}
else
puts("infinity");
}
else
puts("infinity");
}
else
puts("infinity");
}
else
puts("infinity");
}
return 0;
}
- 泰勒公式
//G:泰勒展开
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
const int N=1e5+10;
int n,t,a[N],b[N];
LL res;
int main()
{
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);
if(!t)
puts("0");
else
{
for(int i=1;i<t;i++)
{
res=0;
for(int j=1;j<=n;j++)
res+=a[j]*pow(-b[j],i-1)*b[j];
if(res)
{
puts("infinity");
return 0;
}
}
for(int i=1;i<=n;i++)res+=a[i]*pow(-b[i],t-1)*b[i];
res/=t;
printf("%lld\n",res);
}
return 0;
}
L Euler Function
Description
The Euler function, \(φ\), is known to be important in math theory. Given a positive integer \(n\), \(φ(n)\) is defined as the number of integers in \([1,n]\) that are co-prime with \(n\). For example, \(φ(1)=1,φ(10)=4,φ(11)=10\).
Now, given an array \(x\) with \(n\) positive integers $x_1,…,x_n, your task is to maintain \(m\) operations on \(x\), which can be categorized into two types:
-
\(0\,l\, r\, w\), for each index \(i∈[l,r]\), change x_i to \(x_i\times w\).
-
\(1\, l\, r\), calculate and print\((∑_{i=l}^rφ(x_i))\bmod998244353\).
Input
The first line contains two inetegers \(n,m (1≤n,m≤10^5)\).
The second line contains \(n\) integers \(x_1,…,x_n(1≤x_i≤100)\).
Then \(m\) lines follow. The \(i\)-th line describes the \(i\)-th operation. The input guarantees that \(1≤l≤r≤n\) and \(1≤w≤100\).
Output
For each operation of type \(1\), output a single line with a single integer, representing the answer.
Sample Input
5 5
1 2 3 4 5
1 1 5
0 1 3 2
1 1 5
0 2 5 6
1 1 5
Sample Output
10
11
37
解题思路
- 时间复杂度:\(O()\)
代码
M Addition
Description
The numbers in the computer are usually stored in binary form. But in Little A's computer, the numbers are stored in a different way.
The computer uses n bits to store a number. The value it stores is \(∑_{i=0}^{n−1}v_isgn_i2^i\)
, where \(v\) is an array of length \(n\) containing only \(0\) and \(1\), and \(sgn\) is a predefined array of length \(n\) containing only \(−1\) and \(1\). It is not difficult to find that every expressible integer has a unique expression.
Little A gives you the binary representation of \(a\) and \(b\) in his computer, and you should report the binary representation of \(a+b\) in his computer. It is guaranteed that \(max{∣a∣,∣b∣}≤10
^8\)
, and all integers in \([−10^9,10^9]\) can be expressed in his computer.
Input
The first line contains an integer \(n\), which represents the number of bits used to store an integer.
The second line contains \(n\) integers, and the \(i\)-th of them represents \(sgn_{i−1}\) .
The third line contains \(n\) integers, and the \(i\)-th of them represents \(va_{i−1}\) . The value of a is \(∑_{i=0}^{n−1}va_isgn_i2^i\) .
The fourth line contains \(n\) integers, and the \(i\)-th of them represents $vb_{i−1}. The value of \(b\) is \(∑_{i=0}^{n−1}vb_isgn_i2^i\).
It is guaranteed that \(32≤n≤60,sgn_i∈{−1,1},va _i,vb_i ∈{0,1}\), and \(max{∣a∣,∣b∣}≤10^8\).
Output
Output one line containing \(n\) integers, separated by spaces. The \(i\)-th of them represents \(vc_{i−1}∈{0,1}\). There should be no extra spaces at the end of the line.
You should guarantee that \(a+b=∑_{i=0}^{n−1}vc_isgn_i2^i\).
Your output must be in a single line.
Sample Input
32
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sample Output
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
解题思路
模拟二进制加法
与二进制不同的是,本题多了每位的符号位,关键在于处理进位,当当前位与后一位符号位相同时,后一位加上的正是进位,否则是进位的相反数,由于一开始的进位 \(carry=0\),对下一位的进位只能是 \(0\sim 1 \times sgn[2]\),即:\(-1\sim 1\),故:\(a[i]+b[i]+carry\) 最小是 \(-1\) (即需借位),最大是 \(3\) ,分别讨论即可~
- 时间复杂度:\(O(n)\)
代码
#include<bits/stdc++.h>
using namespace std;
const int N=65;
int a[N],b[N],c[N],sgn[N],n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&sgn[i]);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
int carry=0;
for(int i=1;i<=n;i++)
{
carry*=sgn[i];
int t=a[i]+b[i]+carry;
if(t==0||t==1)
{
c[i]=t;
carry=0;
}
if(t==2)
{
c[i]=0;
carry=1;
}
if(t==3)
{
c[i]=1;
carry=1;
}
if(t==-1)
{
c[i]=1;
carry=-1;
}
carry*=sgn[i];
}
for(int i=1;i<=n;i++)printf("%d%c",c[i]," "[i==n]);
return 0;
}