新的一周...>_<
7.25
hdu 5750 Dertouzos
定义 d 为 一个数的最大的除它本身的约数,给出 n,D,问小于 n 的数里有多少个数的d 为 D
比赛的时候 只想到 去 算 比d的最小质因数还小的素数的个数
还有 一个数的范围的条件,x <= (n-1)/d
所以 x 的范围 是 min(md[d],(n-1)/d)
还有没想到 的是 分一下 d 是大数还是 小数的情况
然后...就自信满满地...既没有用upper_bound 去找个数 还用了个挫挫的筛 ,还每次找最小质因数的时候去筛一次...
F5了三次还在running 就知道 T掉了 ...TWT
T的就是我这样的sb..
抄了 一神 的筛..orz
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <cstdio> 5 using namespace std; 6 const int maxn = 1e7+5; 7 int n,d,pr[maxn],md[maxn]; 8 9 void GetPrime(){ 10 for(int i = 2;i < maxn;i++){ 11 if(!pr[i]) pr[++pr[0]] = i,md[i] = i; 12 for(int j = 1;j <= pr[0] && pr[j]*i < maxn;j++){ 13 pr[i*pr[j]] = 1; 14 md[i*pr[j]] = pr[j]; 15 if(i % pr[j] == 0) break; 16 } 17 } 18 } 19 20 void solve(){ 21 int ans = 0; 22 if(d <= maxn) ans = upper_bound(pr+1,pr+pr[0]+1,min((n-1)/d,md[d])) -pr-1; 23 else{ 24 for(int i = 1;pr[i] <= (n-1)/d && i <= pr[0];i++){ 25 ans = i; 26 if(d%pr[i] == 0) break; 27 } 28 } 29 printf("%d\n",ans); 30 } 31 32 int main(){ 33 GetPrime(); 34 int T; 35 scanf("%d",&T); 36 while(T--){ 37 scanf("%d %d",&n,&d); 38 solve(); 39 } 40 return 0; 41 }
cf 364div2 c They Are Everywhere
给一排字母,问能够覆盖到每种字母的最短区间是多长
第一反应是枚举左端点,二分右端点,维护一个最大值..
还是不会写二分...一直 wa ,差点错过早上的公交车..sigh
一神教第二遍..我太笨了
确定端点的时候,看左边可行,还是右边可行,
如果 是 右边可行的话,l = mid+1
如果是左边可行的话,l = mid
可行的点,不要动他 !!!!!
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 using namespace std; 7 const int maxn = 1e5+5; 8 char s[maxn]; 9 int a[maxn][55],n,m; 10 11 int id (char x){ 12 int num = 0; 13 if(x >= 'A' && x <= 'Z') return x-'A'; 14 if(x >= 'a' && x <= 'z') return x-'a'+26; 15 } 16 17 int ok(int l,int r){ 18 int cnt = 0; 19 for(int i = 0;i <= 51;i++){ 20 int tmp = a[r][i] - a[l-1][i]; 21 if(tmp != 0){ 22 cnt++; 23 } 24 } 25 return cnt; 26 } 27 28 void solve(){ 29 memset(a,0,sizeof(a)); 30 set<char> S; 31 for(int i = 1;i <= n;i++){ 32 for(int j = 0;j <= 51;j++) a[i][j] = a[i-1][j]; 33 a[i][id(s[i])] = a[i-1][id(s[i])]+1; 34 S.insert(s[i]); 35 } 36 m = S.size(); 37 int ans = n+1; 38 int lb,ub,mid; 39 for(int i = 1;i <= n;i++){ 40 lb = i,ub = n; 41 if(ok(lb,ub) < m) continue; 42 while(lb < ub){ 43 mid = lb+(ub-lb)/2; 44 if(ok(i,mid) < m) lb = mid+1; 45 else ub = mid; 46 //printf("i = %d lb = %d ub = %d mid = %d\n",i,lb,ub,mid); 47 } 48 //printf("------ i = %d lb = %d ub = %d\n",i,lb,ub); 49 if(ok(i,lb) == m){ 50 // printf("====ok(%d,%d) = %d\n",i,lb,ok(i,lb)); 51 ans = min(ans,lb-i+1); 52 } 53 if(ok(i,ub) == m){ 54 // printf("================ok(%d,%d) = %d\n",i,ub,ok(i,ub)); 55 ans = min(ans,ub-i+1); 56 } 57 } 58 printf("%d\n",ans); 59 } 60 61 int main(){ 62 while(scanf("%d",&n) != EOF){ 63 scanf("%s",s+1); 64 solve(); 65 } 66 return 0; 67 }
7.26
多校懵逼
7.27
不懂搞死小圆
7.28
多校懵逼
n 棵植物共m种,和它们的坐标,每次操作可以将一盆植物挪到任意位置,求将m种植物挪成1 2 3 ... m 这样排列的至少需要挪多少次
和上周的bc的第二题一样,求出以 a[i] 为结尾的LIS ,扫一遍求个最小值
上周bc 是抄的板,这个是自己写的了
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1e5+5; 7 int a[maxn],b[maxn],c[maxn],n,m; 8 int dp[maxn]; 9 10 int lowbit(int x){return x & (-x);} 11 12 int query(int x){ 13 int ret = 0; 14 while(x){ 15 ret = max(ret,c[x]); 16 x -= lowbit(x); 17 } 18 return ret; 19 } 20 21 void update(int x,int d){ 22 while(x < maxn){ 23 c[x] = max(c[x],d); 24 x += lowbit(x); 25 } 26 } 27 28 void solve(){ 29 memset(dp,0,sizeof(dp)); 30 for(int i = 1;i <= n;i++){ 31 dp[i] = query(a[i])+1; 32 update(a[i],dp[i]); 33 } 34 //for(int i = 1;i <= n;i++) printf("%d ",dp[i]); 35 //printf("\n"); 36 int ans = n+1; 37 for(int i = 1;i <= n;i++) ans = min(ans,n-dp[i]); 38 printf("%d\n",ans); 39 } 40 41 int main(){ 42 while(scanf("%d %d",&n,&m) != EOF){ 43 double x; 44 for(int i = 1;i <= n;i++) scanf("%d %lf",&a[i],&x); 45 memset(c,0,sizeof(c)); 46 solve(); 47 } 48 return 0; 49 }
7.29
还是不懂搞死小圆
不懂bonds
7.30
写了个点双缩点再求 LCA wa了一天...开始怀疑狗生
司老大曰:这不是很正常的嘛
实习受挫..
司老大曰:多学点东西不挺好吗,慢慢来
谨记司老大教诲>_<
其实我是有做bc 的TwT,先看的1002, 想到的时候 1002的时候 都过了300人了,就没打了..
接着看1003..没有想到 把 y 拆成 y = z*z 这个形式,瞎打表找规律半天 GG了
hdu 5776 sum
给出一个序列,问是否存在连续一段子序列的和是m的倍数
如果 m <= n 肯定是可以的,如果 m > n 就看一个余数是不是出现了两次,如果出现了两次,这一段的和就一定能整除m
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 1e5+5; 7 int n,m,vis[maxn],a[maxn]; 8 9 void solve(){ 10 memset(vis,0,sizeof(vis)); 11 if(m <= n){ 12 puts("YES"); 13 return; 14 } 15 memset(vis,0,sizeof(vis)); 16 int sum = 0; 17 for(int i = 1;i <= n;i++){ 18 sum += a[i]; 19 sum = sum%m; 20 if(vis[sum] || sum == 0){ 21 puts("YES"); 22 return; 23 } 24 vis[sum] = 1; 25 } 26 puts("NO"); 27 } 28 29 int main(){ 30 int T; 31 scanf("%d",&T); 32 while(T--){ 33 scanf("%d %d",&n,&m); 34 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 35 solve(); 36 } 37 return 0; 38 }
hdu 5777 domino
n 个骨牌,高度可以自己任意定,但是至少高为 1,相邻两个骨牌的距离为 di 可以推k次,可以选择往左或者往右推,碰倒相邻 的条件是高度至少为di+1,问推倒所有骨牌的骨牌高度和最少是多少
如果 k = n 的话,就分别推倒每个就好了
如果 k = n-1的话,就去找一个 d 最小的来被推倒..
...所以sort 一下找 n-k就可以了
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 const int maxn = 1e5+5; 8 int n,k,a[maxn]; 9 typedef long long LL; 10 11 void solve(){ 12 sort(a+1,a+n); 13 LL ans = 1LL*n; 14 for(int i = 1;i <= n-k;i++) ans += a[i]; 15 printf("%I64d\n",ans); 16 } 17 18 int main(){ 19 int T; 20 scanf("%d",&T); 21 while(T--){ 22 scanf("%d %d",&n,&k); 23 for(int i = 1;i <= n-1;i++) scanf("%d",&a[i]); 24 solve(); 25 } 26 return 0; 27 }
hdu 5778 abs
给出 x ,要找出 这样 的 y ,使得abs(y-x)最小 y >= 2 y的所有质因数的个数都为 2
拆成 y = z*z 的形式...这样就判断 z 的每个质因数 是不是 只出现了一次
没想到...我好菜啊..
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 typedef long long LL; 8 LL n,sq; 9 10 bool check(LL y){ 11 int cnt; 12 for(LL j = 2;1LL*j*j <= y;j++){ 13 if(y%j == 0){ 14 cnt = 0; 15 while(y%j == 0){ 16 cnt++; 17 y = y/j; 18 if(cnt > 1) return false; 19 } 20 } 21 } 22 cnt = 0; 23 if(y > 1) cnt++; 24 return true; 25 } 26 27 LL ok(int x){ 28 for(LL i = sq+x;;i = i+x){ 29 if(check(i)){ 30 return abs(n-i*i); 31 } 32 } 33 } 34 35 void solve(){ 36 if(n <= 4){ 37 printf("%I64d\n",4-n); 38 return; 39 } 40 sq = sqrt(n); 41 LL ans = 1LL << 60; 42 if(check(sq)){ 43 ans = min(ans,abs(n-sq*sq)); 44 //printf("ans1 = %I64d\n",ans); 45 } 46 ans = min(ans,ok(1)); 47 //printf("ans2 = %I64d\n",ans); 48 ans = min(ans,ok(-1)); 49 //printf("ans3 = %I64d\n",ans); 50 printf("%I64d\n",ans); 51 } 52 53 int main(){ 54 int T; 55 scanf("%d",&T); 56 while(T--){ 57 scanf("%I64d",&n); 58 solve(); 59 } 60 return 0; 61 }