atcoder beginer 347 (abc347) D E 题解
D
就是二进制下,哪些位置有重合(两个1),哪些位置没有重合(1个1,1个0),剩下的都是0。
xor的结果<2^60,就是小于60位(二进制下)。注意要有要求两个数需要是2^60,于是要有大小的判断,因为有的a,b会2^60,但是按照题目要求,这个情况不行。
比如xor的结果,60位都是1,然后a、b各有60个1,那么需要有30个1重合,然后a、b的最高位数是90。
比如xor的结果,是1后面59个0,a、b各有30、31个1,那么有30个1重合,然后a、b的最高位数是61(这个是比较特殊的样例,a的位数+b的位数-xor的位数<60但,xor的位数却大于60)。
另外,调试,也可以用assert(rx<(1ll<<60));的方式。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdbool> 6 #include <string> 7 #include <algorithm> 8 #include <iostream> 9 #include <sstream> 10 #include <ctime> 11 #include <stack> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 #include <array> 17 #include <assert.h> 18 using namespace std; 19 #define LL long long 20 #define ULL unsigned long long 21 22 const LL mod_1=1e9+7; 23 const LL mod_2=998244353; 24 25 const double eps_1=1e-5; 26 const double eps_2=1e-10; 27 28 const int maxn=500; 29 30 31 LL w[maxn],x[maxn],y[maxn]; 32 33 int main() 34 { 35 LL a,b,c,len=0,cnt_one=0,cnt_loop,rx,ry; 36 LL i; 37 38 cin>>a>>b>>c; 39 40 memset(w,0,sizeof(w)); 41 42 while (c) 43 { 44 w[len]=c&1; 45 c=c>>1; 46 cnt_one+=w[len]; 47 len++; 48 } 49 50 if (abs(a-b)>cnt_one || a+b<cnt_one || (a+b-cnt_one)%2==1) // || (a+b-cnt_one>60) 51 { 52 cout << "-1"; 53 return 0; 54 } 55 56 //cout << "-2"; 57 //return 0; 58 59 cnt_loop=(a+b-cnt_one)/2; 60 a-=cnt_loop; 61 b-=cnt_loop; 62 63 memset(x,0,sizeof(x)); 64 memset(y,0,sizeof(y)); 65 66 for (i=0;i<len;i++) 67 if (w[i]==1) 68 { 69 if (a>0) 70 { 71 x[i]=1; 72 a--; 73 } 74 else if (b>0) 75 { 76 y[i]=1; 77 b--; 78 } 79 } 80 81 for (i=0;i<maxn;i++) 82 if (cnt_loop>0 && x[i]==0 && y[i]==0) 83 { 84 x[i]=1; 85 y[i]=1; 86 cnt_loop--; 87 } 88 89 rx=0; 90 for (i=maxn-1;i>=0;i--) 91 rx=(rx<<1ll)|x[i]; 92 ry=0; 93 for (i=maxn-1;i>=0;i--) 94 ry=(ry<<1ll)|y[i]; 95 96 97 //assert(rx<(1ll<<60)); 98 //assert(ry<(1ll<<60)); 99 100 for (i=maxn-1;i>=60;i--) 101 if (x[i]==1 || y[i]==1) 102 { 103 cout << "-1"; 104 return 0; 105 } 106 107 //cout << (1ll<<60) <<endl; ///要打括号,否则输出160 108 109 cout<<rx<<" "<<ry<<endl; 110 return 0; 111 } 112 /* 113 114 3 0 7 115 116 59 0 1152921504606846975 117 60 0 1152921504606846975 118 119 1 0 1152921504606846976 120 121 122 0 0 1152921504606846976 123 0 60 1152921504606846976 124 60 0 1152921504606846976 125 0 1 1152921504606846976 126 59 0 1152921504606846975 127 128 0 2 3 129 0 3 88 130 0 4 88 131 */
E
题目转化为一个数,是从什么时候开始出现,什么时候结束,然后可能有若干个循环。
否则,解法,可能是不是如可持久化这种奇怪的东西……因为一次只变一个数字。
那么多人通过这道题,是应该想一下原因。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <cstdbool> 6 #include <string> 7 #include <algorithm> 8 #include <iostream> 9 #include <sstream> 10 #include <ctime> 11 #include <stack> 12 #include <vector> 13 #include <queue> 14 #include <set> 15 #include <map> 16 #include <array> 17 using namespace std; 18 #define LL long long 19 #define ULL unsigned long long 20 21 const LL mod_1=1e9+7; 22 const LL mod_2=998244353; 23 24 const double eps_1=1e-5; 25 const double eps_2=1e-10; 26 27 const int maxn=2e5+10; 28 29 int f[maxn], cnt[maxn]; 30 LL total_cnt[maxn], result[maxn]; 31 32 vector<pair<int,int> > vec[maxn]; 33 34 35 int main() 36 { 37 int n,q,d,ind, number=0,i; 38 scanf("%d%d",&n,&q); 39 40 for (ind=1;ind<=q;ind++) 41 { 42 scanf("%d",&d); 43 44 if (f[d]==0) 45 { 46 f[d]=ind; 47 number++; 48 cnt[ind]=number; 49 } 50 else 51 { 52 vec[d].push_back( make_pair(f[d],ind-1) ); 53 f[d]=0; 54 number--; 55 cnt[ind]=number; 56 } 57 } 58 59 for (i=1;i<=n;i++) 60 if (f[i]!=0) 61 vec[i].push_back( make_pair(f[i], q)); 62 63 total_cnt[0]=0; 64 for (i=1;i<=q;i++) 65 total_cnt[i]=total_cnt[i-1]+cnt[i]; 66 for (i=1;i<=n;i++) 67 { 68 for (auto pai:vec[i]) 69 { 70 result[i] += total_cnt[pai.second] - total_cnt[pai.first-1]; 71 } 72 } 73 74 for (i=1;i<=n;i++) 75 { 76 cout<<result[i]; 77 if (i==n) 78 cout<<endl; 79 else 80 cout<<" "; 81 } 82 83 return 0; 84 }