做多校被虐成狗了---什么都不会啊~~
还是觉得把能够想懂一点的,不管是看的别人的题解或者代码的,还是看的标程的,都记录一下--
加油------
1001 Magician
1002 RGCDQ
先筛素数,然后记录
prime[1] = 2;
prime[2] = 3;
prime[3] = 5;
prime[4] = 7;
prime[5]=11;
记录下这个是为了计算cnt[]数组,cnt[i]表示i由几种素数构成
再算pre[i][j]表示的是前i个数,f(i) = j的数的个数
然后再查询就可以了。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 8 const int maxn = 1000005; 9 int prime[maxn],vis[maxn],cnt[maxn],pre[maxn][8]; 10 int mark[15]; 11 12 int main(){ 13 14 memset(cnt,0,sizeof(cnt)); 15 memset(pre,0,sizeof(pre)); 16 17 int t = 0; 18 19 memset(vis,0,sizeof(vis)); 20 int m = sqrt(maxn +0.5); 21 for(int i = 2;i <= m;i++) if(!vis[i]) 22 for(int j = i*i;j <= maxn;j+=i) vis[j] = 1; 23 24 for(int i = 2;i <= maxn;i++) if(!vis[i]) 25 prime[++t] = i; 26 27 for(int i=1;i<=t;i++) 28 for(int j=1;prime[i]*j<=maxn;j++) 29 cnt[prime[i]*j]++; 30 31 32 33 for(int i = 1;i <= 8;i++){ 34 for(int j = 1;j <= maxn;j++){ 35 pre[j][i] += pre[j-1][i]; 36 if(cnt[j] == i) pre[j][i]++; 37 } 38 } 39 40 // for(int i = 1;i <= 20;i++) printf("cnt[%d] = %d\n",i,cnt[i]); 41 42 int q; 43 scanf("%d",&q); 44 while(q--){ 45 int l,r; 46 scanf("%d %d",&l,&r); 47 memset(mark,0,sizeof(mark)); 48 for(int i = 1;i <= 7;i++) mark[i] = pre[r][i] - pre[l-1][i]; 49 50 if(mark[7] >= 2) printf("7\n"); 51 else if(mark[6] >= 2) printf("6\n"); 52 else if(mark[5] >= 2) printf("5\n"); 53 else if(mark[4] >= 2) printf("4\n"); 54 else if((mark[3] >= 2) || (mark[3] && mark[6])) printf("3\n"); 55 else if((mark[2] >= 2) || (mark[2] &&mark[4]) || (mark[2] && mark[6])) printf("2\n"); 56 else printf("1\n"); 57 } 58 return 0; 59 }
1004 1004 Painter
按照"\","/"这两个方向分别去扫一遍连续的段数就可以了
虽然知道这么做--可是代码改了好久----
代码能力真是太弱了---
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 char g[55][55]; 9 int vis[55][55]; 10 int n,len; 11 12 void dfs1(int x,int y){ 13 vis[x][y]--; 14 // printf("vis[%d][%d] = %d\n",x,y,vis[x][y]); 15 if(x+1 > n || y+1 > 50) return; 16 if(g[x+1][y+1] == ‘B‘ || g[x+1][y+1] == ‘.‘) return; 17 dfs1(x+1,y+1); 18 } 19 20 void dfs2(int x,int y){ 21 vis[x][y]--; 22 // printf("vis[%d][%d] = %d\n",x,y,vis[x][y]); 23 if(x+1 > n || y-1 < -1) return; 24 if(g[x+1][y-1] == ‘R‘ || g[x+1][y-1] == ‘.‘) return; 25 dfs2(x+1,y-1); 26 } 27 28 29 int main(){ 30 int T; 31 scanf("%d",&T); 32 while(T--){ 33 scanf("%d",&n); 34 for(int i = 0;i < n;i++) cin >> g[i]; 35 36 for(int i = 0;i < n;i++){ 37 for(int j = 0;j < 55;j++){ 38 vis[i][j] = 1; 39 } 40 } 41 42 int ans = 0; 43 for(int i = 0;i < n;i++){ 44 for(int j = 0;j < strlen(g[i]);j++){ 45 if(vis[i][j] == 1 && (g[i][j] == ‘R‘ || g[i][j] == ‘G‘) ){ 46 dfs1(i,j); 47 ans++; 48 // printf("ans = %d\n",ans); 49 } 50 } 51 } 52 53 for(int i = 0;i < n;i++){ 54 for(int j = 0;j < 55;j++){ 55 if(g[i][j] == ‘G‘) vis[i][j] = 1; 56 } 57 } 58 // printf("2222\n"); 59 for(int i = 0;i < n;i++){ 60 for(int j = 0;j < strlen(g[i]);j++){ 61 if(vis[i][j] == 1 && (g[i][j] == ‘B‘ || g[i][j] == ‘G‘) ){ 62 dfs2(i,j); 63 ans++; 64 // printf("ans = %d\n",ans); 65 } 66 } 67 } 68 printf("%d\n",ans); 69 } 70 return 0; 71 }
1005 Fan Li
1006 Beautiful Set
1007 Hope
1008 Solve this interesting problem
可以从这个图里面看出来,左区间的长度有两种情况
左区间 = 右区间
左区间 = 右区间+1
然后枚举给出的[L,R]区间作为当前的左区间还是右区间
当L == 0的时候,更新n的值
自己写的时候崩掉了~~后来看的别人的代码
代码里面如果先枚举作为右区间的情况的话,就会RE,不懂为什么~~
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<algorithm> 11 using namespace std; 12 13 typedef long long LL; 14 const long long INF = 1e18; 15 const int mod=1000000007; 16 const int maxn=1000005; 17 18 LL L,R; 19 LL res; 20 21 void dfs(LL l,LL r){ 22 if(r >= res ) return; 23 if(l < 0) return; 24 if(l == 0){ 25 res = r; 26 return; 27 } 28 29 if(r-l+1 > l) return; 30 dfs(l-(r-l+1),r); 31 dfs(l-(r-l+1)-1,r); 32 dfs(l,r+(r-l+1)); 33 dfs(l,r+(r-l+1)-1); 34 35 } 36 37 int main(){ 38 while(cin>>L >> R){ 39 res = INF; 40 dfs(L,R); 41 if(res != INF) cout << res <<"\n"; 42 else printf("-1\n"); 43 } 44 return 0; 45 }
1009 Boring Class
1010 Crazy Bobo
不知道这题是不是真的懂了
按照官方题解说的,
如果w[u] > w[v],那么就从u到v连一条边
再树dp(其实也不懂树dp,可是看代码就好理解了)
就相当于把图转化了,只有满足w[u] < w[v],才存在边,再到这里面去找能够联通的块里面最多有几个节点
后来想,递增和递减是相互的,如果w[u] > w[v],那么就从v到u连一条边,这样来做可不可以呢
画一下样例的图就知道不对
上面是递减的
下面是递增的
1011 Work
dfs一下就可以了
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 int n,k; 9 const int maxn =1005; 10 vector<int> g[maxn]; 11 int cnt; 12 13 void dfs(int u){ 14 for(int i = 0;i < g[u].size();i++){ 15 int v = g[u][i]; 16 cnt++; 17 dfs(v); 18 } 19 } 20 21 int main(){ 22 while(scanf("%d %d",&n,&k) != EOF){ 23 for(int i = 1;i <= n;i++) g[i].clear(); 24 for(int i = 1;i < n;i++){ 25 int u,v; 26 scanf("%d %d",&u,&v); 27 g[u].push_back(v); 28 } 29 int ans = 0; 30 for(int i = 1;i <= n;i++){ 31 cnt = 0; 32 dfs(i); 33 // printf("cnt = %d\n",cnt); 34 if(cnt == k) ans ++; 35 } 36 printf("%d\n",ans); 37 } 38 return 0; 39 }