A - Classy Numbers(数位dp)
Let's call some positive integer classy if its decimal representation contains no more than 33 non-zero digits. For example, numbers 44, 200000200000, 1020310203 are classy and numbers 42314231, 102306102306, 72774200007277420000 are not.
You are given a segment [L;R][L;R]. Count the number of classy integers xx such that L≤x≤RL≤x≤R.
Each testcase contains several segments, for each of them you are required to solve the problem separately.
Input
The first line contains a single integer TT (1≤T≤1041≤T≤104) — the number of segments in a testcase.
Each of the next TT lines contains two integers LiLi and RiRi (1≤Li≤Ri≤10181≤Li≤Ri≤1018).
Output
Print TT lines — the ii-th line should contain the number of classy integers on a segment [Li;Ri][Li;Ri].
Example
Input
4
1 1000
1024 1024
65536 65536
999999 1000001
Output
1000
1
0
2
算是一个数位dp的模板题吧,如果没看过数位dp可以看下我的博客里的这一篇。
这里要求是找不超过3个非0的数字组成的数,那么state就用来计非0数字的数目。还是看代码里的注释吧
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
ll a[20];
ll dp[20][4]; //因为要用到1,2,3,所以二维数组要开到4
ll dfs(int pos,int state,bool limit)//pos代表位数,state记录非0数字的个数,limit数位上界变量
{
if(state>3) //数字个数大于3个,那么返回0
return 0;
if(pos==0)
return 1;
if(!limit&&dp[pos][state]!=-1) //记忆化
return dp[pos][state];
int up=limit?a[pos]:9;
ll ans=0;
for(int i=0;i<=up;i++){
ans+=dfs(pos-1,state+(i==0?0:1),limit&&i==a[pos]);
}
if(!limit)
dp[pos][state]=ans;
return ans;
}
ll solve(ll x)//数位分解
{
met(dp,-1);
int pos=1;
while(x){
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,1);
}
int main()
{
int t;
sc(t);
while(t--){
met(a,0);
ll l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",solve(r)-solve(l-1));
}
}
C - Function Height
You are given a set of 2n+12n+1 integer points on a Cartesian plane. Points are numbered from 00 to 2n2n inclusive. Let PiPi be the ii-th point. The xx-coordinate of the point PiPi equals ii. The yy-coordinate of the point PiPi equals zero (initially). Thus, initially Pi=(i,0)Pi=(i,0).
The given points are vertices of a plot of a piecewise function. The jj-th piece of the function is the segment PjPj+1PjPj+1.
In one move you can increase the yy-coordinate of any point with odd xx-coordinate (i.e. such points are P1,P3,…,P2n−1P1,P3,…,P2n−1) by 11. Note that the corresponding segments also change.
For example, the following plot shows a function for n=3n=3 (i.e. number of points is 2⋅3+1=72⋅3+1=7) in which we increased the yy-coordinate of the point P1P1 three times and yy-coordinate of the point P5P5 one time:
Let the area of the plot be the area below this plot and above the coordinate axis OX. For example, the area of the plot on the picture above is 4 (the light blue area on the picture above is the area of the plot drawn on it).
Let the height of the plot be the maximum yy-coordinate among all initial points in the plot (i.e. points P0,P1,…,P2nP0,P1,…,P2n). The height of the plot on the picture above is 3.
Your problem is to say which minimum possible height can have the plot consisting of 2n+12n+1 vertices and having an area equal to kk. Note that it is unnecessary to minimize the number of moves.
It is easy to see that any answer which can be obtained by performing moves described above always exists and is an integer number not exceeding 10181018.
Input
The first line of the input contains two integers nn and kk (1≤n,k≤10181≤n,k≤1018) — the number of vertices in a plot of a piecewise function and the area we need to obtain.
Output
Print one integer — the minimum possible height of a plot consisting of 2n+12n+1vertices and with an area equals kk. It is easy to see that any answer which can be obtained by performing moves described above always exists and is an integer number not exceeding 10181018.
Examples
Input
4 3
Output
1
Input
4 12
Output
3
Input
999999999999999999 999999999999999986
Output
1
Note
One of the possible answers to the first example:
The area of this plot is 3, the height of this plot is 1.
There is only one possible answer to the second example:
The area of this plot is 12, the height of this plot is 3.
这个题大体的题意是给2n+1个点(包括原点),构成三角形,这些三角形的总面积加起来为k,求三角形的顶点平均高度尽可能小的情况下,最大的顶点高度。
因为底是2,所以每个三角形面积即为高
当n>=k时,直接输出1;
如果n<k,则为k/n向上取整
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
ll n,k;
int main()
{
while(~scanf("%lld%lld",&n,&k)){
if(n>=k)
printf("1\n");
else{
if(k%n==0)
printf("%lld\n",k/n);
else printf("%lld\n",k/n+1);
}
}
}
D - Diagonal Walking v.2
Mikhail walks on a Cartesian plane. He starts at the point (0,0)(0,0), and in one move he can go to any of eight adjacent points. For example, if Mikhail is currently at the point (0,0)(0,0), he can go to any of the following points in one move:
- (1,0)(1,0);
- (1,1)(1,1);
- (0,1)(0,1);
- (−1,1)(−1,1);
- (−1,0)(−1,0);
- (−1,−1)(−1,−1);
- (0,−1)(0,−1);
- (1,−1)(1,−1).
If Mikhail goes from the point (x1,y1)(x1,y1) to the point (x2,y2)(x2,y2) in one move, and x1≠x2x1≠x2and y1≠y2y1≠y2, then such a move is called a diagonal move.
Mikhail has qq queries. For the ii-th query Mikhail's target is to go to the point (ni,mi)(ni,mi) from the point (0,0)(0,0) in exactly kiki moves. Among all possible movements he want to choose one with the maximum number of diagonal moves. Your task is to find the maximum number of diagonal moves or find that it is impossible to go from the point (0,0)(0,0) to the point (ni,mi)(ni,mi) in kiki moves.
Note that Mikhail can visit any point any number of times (even the destination point!).
Input
The first line of the input contains one integer qq (1≤q≤1041≤q≤104) — the number of queries.
Then qq lines follow. The ii-th of these qq lines contains three integers nini, mimi and kiki(1≤ni,mi,ki≤10181≤ni,mi,ki≤1018) — xx-coordinate of the destination point of the query, yy-coordinate of the destination point of the query and the number of moves in the query, correspondingly.
Output
Print qq integers. The ii-th integer should be equal to -1 if Mikhail cannot go from the point (0,0)(0,0) to the point (ni,mi)(ni,mi) in exactly kiki moves described above. Otherwise the ii-th integer should be equal to the the maximum number of diagonal moves among all possible movements.
Example
Input
3
2 2 3
4 3 7
10 1 9
Output
1
6
-1
Note
One of the possible answers to the first test case: (0,0)→(1,0)→(1,1)→(2,2)(0,0)→(1,0)→(1,1)→(2,2).
One of the possible answers to the second test case: (0,0)→(0,1)→(1,2)→(0,3)→(1,4)→(2,3)→(3,2)→(4,3)(0,0)→(0,1)→(1,2)→(0,3)→(1,4)→(2,3)→(3,2)→(4,3).
In the third test case Mikhail cannot reach the point (10,1)(10,1) in 9 moves.
题意大体是从(0,0)走到(n,m),最多走k步,可以横着竖着或者斜着走,问可以最多斜着走几步?
这个题算是找规律把,画上几个图就可以了。
当n或m有一个大于k时,就以为这无论如何都走不到目的地,所以直接输出-1.
如果n-m(n为两个数中大的那一个)为奇数,那么就有一步不能走对角线,k要减一,
或者如果走对角线可以直接到终点,k-n(n还是为大的那个)为偶数,k不变(因为除了终点其他点可以多次经过),如果为奇数,就有两步不能走对角线,k-=2;
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
ll n,m,k;
int main()
{
int t;
sc(t);
while(t--){
scanf("%lld%lld%lld",&n,&m,&k);
if(n>k||m>k)
printf("-1\n");
else {
if(n<m)
swap(n,m);
if((n-m)&1)
k--;
else if((k-n)&1)
k-=2;
printf("%lld\n",k);
}
}
}
还有一个因为没有看群通知所以做了其他的一个题,在这里也写上吧。
GCD Again
Problem Description
Do you have spent some time to think and try to solve those unsolved problem after one ACM contest?
No? Oh, you must do this when you want to become a "Big Cattle".
Now you will find that this problem is so familiar:
The greatest common divisor GCD (a, b) of two positive integers a and b, sometimes written (a, b), is the largest divisor common to a and b. For example, (1, 2) =1, (12, 18) =6. (a, b) can be easily found by the Euclidean algorithm. Now I am considering a little more difficult problem:
Given an integer N, please count the number of the integers M (0<M<N) which satisfies (N,M)>1.
This is a simple version of problem “GCD” which you have done in a contest recently,so I name this problem “GCD Again”.If you cannot solve it still,please take a good think about your method of study.
Good Luck!
Input
Input contains multiple test cases. Each test case contains an integers N (1<N<100000000). A test case containing 0 terminates the input and this test case is not to be processed.
Output
For each integers N you should output the number of integers M in one line, and with one line of output for each line in input.
Sample Input
2 4 0
Sample Output
0 1
Author
lcy
题意:给一个N,找小于N里的与N的最大公约数大于1,也就是等价于找出小于N且与N不互质的数的个数,很明显套欧拉函数的模板就好了,ans=N-1-φ(N)。(-1是因为要减去1)。欧拉函数我没写博客,不会的可以百度一下。我当时看的是这一篇
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
int n;
int euler(int n)
{
int num=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
num=num/i*(i-1);
while(n%i==0)
n/=i;
}
}
if(n>1)
num=num/n*(n-1);
return num;
}
int main()
{
while(~sc(n),n!=0){
printf("%d\n",n-1-euler(n));
}
}
刚刚又补了一个题。。。
E - Vasya and Arrays
Vasya has two arrays AA and BB of lengths nn and mm, respectively.
He can perform the following operation arbitrary number of times (possibly zero): he takes some consecutive subsegment of the array and replaces it with a single element, equal to the sum of all elements on this subsegment. For example, from the array [1,10,100,1000,10000][1,10,100,1000,10000] Vasya can obtain array [1,1110,10000][1,1110,10000], and from array [1,2,3][1,2,3] Vasya can obtain array [6][6].
Two arrays AA and BB are considered equal if and only if they have the same length and for each valid ii Ai=BiAi=Bi.
Vasya wants to perform some of these operations on array AA, some on array BB, in such a way that arrays AA and BB become equal. Moreover, the lengths of the resulting arrays should be maximal possible.
Help Vasya to determine the maximum length of the arrays that he can achieve or output that it is impossible to make arrays AA and BB equal.
Input
The first line contains a single integer n (1≤n≤3⋅105)n (1≤n≤3⋅105) — the length of the first array.
The second line contains nn integers a1,a2,⋯,an (1≤ai≤109)a1,a2,⋯,an (1≤ai≤109) — elements of the array AA.
The third line contains a single integer m (1≤m≤3⋅105)m (1≤m≤3⋅105) — the length of the second array.
The fourth line contains mm integers b1,b2,⋯,bm (1≤bi≤109)b1,b2,⋯,bm (1≤bi≤109) - elements of the array BB.
Output
Print a single integer — the maximum length of the resulting arrays after some operations were performed on arrays AA and BB in such a way that they became equal.
If there is no way to make array equal, print "-1".
Examples
Input
5 11 2 3 5 7 4 11 7 3 7
Output
3
Input
2 1 2 1 100
Output
-1
Input
3 1 2 3 3 1 2 3
Output
3
题意:给两个数组,这两个数组中相邻的数可以相加,问如果可以让两个数组一模一样,问数组中最多可以有多少个数,一模一样就是说想最后这个例子,两个数组都是1,2,3,数一样,顺序也一样。
首先判断这两个数组的和相不相等,如果不相等直接输出-1,如果相等继续判断,直接模拟就好了,从第一个数组的第一个数判断如果不相等,看看哪个数大,小的那个就往后加,直到相等为止。具体看代码吧。
还要注意如果是int会爆掉,要用long long
#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x) priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=3e5+10;
int n1,n2;
ll a[N],b[N];
int main()
{
while(~scanf("%d",&n1)){
met(a,0);
met(b,0);
for(int i=1;i<=n1;i++){
scanf("%lld",&a[i]);
a[0]+=a[i];
}
sc(n2);
for(int i=1;i<=n2;i++){
scanf("%lld",&b[i]);
b[0]+=b[i];
}
if(a[0]!=b[0])
printf("-1\n");
else {
int ans=0;
int k=1;
for(int i=1;i<=n1;i++,k++){
bool flag=true;
while(a[i]!=b[k]){ //两个数是否相等
if(a[i]>b[k])
b[++k]+=b[k-1];
else
a[++i]+=a[i-1];
if(i>n1||k>n2){ //超出范围就退出
flag=false;
break;
}
}
if(flag==true)
ans++;
}
if(ans==0)
printf("-1\n");
else
printf("%d\n",ans);
}
}
}