2012 Multi-University Training Contest 3
1001 ?hdu 4320 ?http://acm.hdu.edu.cn/showproblem.php?pid=4320
題意:
V寫下一個A進制的任意有限小數,如果S能將其翻譯成B進制的有限小數,則S贏,輸出Yes 否則V贏輸出No;
思路:
只要A的所有質因子都包含在B中,S就能贏(證明沒看懂!!求指教)
這里注意:
(N表示A,B的極限值)
1:一個數i的質因子,至多只會存在一個大于sqrt(i)的。所以這里我們只要枚舉出小于sqrt(N)的所有質數即可,然后用所有小于sqrt(j)的質數來查找j的質因子,同時j也要做相應的除法把枚舉道德質因子除去,當枚舉完所有小于sqrt(j)質數時,j如果>1說明存在大于sqrt(j)的質因子,這時的質因子也就是j本身看了,所以要檢查一下B是否還包含這個質因子,因為當存在大于sqrt(N)的質數時,我們沒有枚舉出來,所以必須在后邊要算。
View Code #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #define maxn 1000007 #define ll __int64 using namespace std;int nop[maxn]; int res[maxn],len; //素數篩選法選出素數 void SP() {len = 0;int i,j;memset(nop,0,sizeof(nop));nop[0] = nop[1] = 1;for (i = 2; i*i < maxn; ++i){if (!nop[i]){for (j = i*2; j < maxn; j += i){nop[j] = 1;}}}for (i = 2; i < maxn; ++i){if (!nop[i]){res[len++] = i;}} }int main() {//freopen("d.txt","r",stdin);int t,i;int cas = 1;ll a,b;SP();/*for (i = 0; i < 50; ++i) printf("%d ",res[i]);puts("");*/scanf("%d",&t);while (t--){scanf("%I64d%I64d",&a,&b);bool flag = false;//枚舉小于sqrt(a)的質因子for (i = 0; res[i] <= sqrt(1.0*a); ++i){if (a%res[i] == 0)//屬于A的質因子一定要屬于B {if (b%res[i] != 0){flag = true;break;}while (a%res[i] == 0)//a必須做相應處理,為后邊出現大雨sqrt(a)的質因子做準備a /= res[i];}}if (b%a != 0) flag = true;//此時a可能是1,也可能是大與sqrt(a)的質因子printf("Case #%d: ",cas++);if (!flag) printf("YES\n");else printf("NO\n");}return 0; }?
還有一個解法:首先明確每一個大于1的整數都能分解成質因數乘積的形式,還要要知道兩個數的最大公約數就是這兩個數的公共質因子的乘積,所以我們只要不斷取他們的公共質因子的乘積,直到a只剩下1時,說明a的所有質因子都包含在b中,就是不斷地取a,b的最大公約數,然后a再除去最大公約數。
View Code #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #define maxn 1000007 #define ll __int64 using namespace std;ll gcd(ll a,ll b) {if (b == 0) return a;return gcd(b,a%b);} int main() {//freopen("d.txt","r",stdin); ll a,b;int t;int cas = 1;scanf("%d",&t);while (t--){scanf("%I64d%I64d",&a,&b);printf("Case #%d: ",cas++);ll c = gcd(a,b);if (c == 1)//如果c為1說明不存在公共質因子 {printf("NO\n");}else{while (c != 1){a/=c;//除去c = gcd(a,b);//再取 }if (a == 1) printf("YES\n");//公共質因子都能取完else printf("NO\n");}}return 0; }?
1004:hdu 4232?http://acm.hdu.edu.cn/showproblem.php?pid=4323
題意:
給出n個數字字符串,然后給出m個詢問,每個詢問包括一個數字字符串和一個最大值,要求在n個字符串里尋找與查詢字符串的字符串編輯距離小于最大值的字符串個數。
思路:
直接利用dp求查詢字符串與n個字符串的編輯距離,求解即可。
View Code #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #define maxn 1507 #define ll __int64 using namespace std;char num[maxn][13]; int d[13][13];bool solve(char *s1,char*s2,int mk) {int i,j;int len1 = strlen(s1);int len2 = strlen(s2);if (abs(len1 - len2) > mk) return false;/*才開始以為只要字符串長度相同他們不同的點個數大于mk標記就返回false結果就wa了例如123324 雖然他們不同的點有三個,我們只要將4刪除,在3前加1即可用兩步操作實現*//*if (len1 == len2){int tmp = 0;for (i = 0; i < len1; ++i){if (s1[i] != s2[i]) tmp++;}if (tmp > mk) return false;}*///關鍵是dp求編輯距離memset(d,0,sizeof(d));d[0][0] = 0;for (i = 1; i <= len1; ++i) d[i][0] = i;for (i = 1; i <= len2; ++i) d[0][i] = i;for (i = 1; i <= len1; ++i){for (j = 1; j <= len2; ++j){d[i][j] = d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1]?0:1);d[i][j] = min(d[i][j],d[i - 1][j] + 1);d[i][j] = min(d[i][j],d[i][j - 1] + 1);}}//printf("%d %d %s %s\n",d[len1][len2],mk,s1,s2);if (d[len1][len2] <= mk) return true;else return false; } int main() {//freopen("d.txt","r",stdin);int t,i,j,n,m;char str[13];int cas = 1,tmp;scanf("%d",&t);while (t--){printf("Case #%d:\n",cas++);scanf("%d%d",&n,&m);memset(num,0,sizeof(num));for (i = 0; i < n; ++i)scanf("%s",num[i]);for (i = 0; i < m; ++i){int ct = 0;scanf("%s%d",str,&tmp);for (j = 0; j < n; ++j){if (solve(str,num[j],tmp))ct++;}printf("%d\n",ct);}}return 0; }?
1005: hdu 4324?http://acm.hdu.edu.cn/showproblem.php?pid=4324
題意:
給定n個人的愛情圖,如果a愛b那么b一定不愛a,而且題目保證任意兩點都存在一條邊(there is love between any of two people,?if A don’t love B, then B must love A)
關系矩陣map[i][j] = 1表示i愛j,那么j一定不愛i,讓你找出是否存在三角戀,即:A loves B, B loves C and C loves A.
思路:
按照官方解題報告的第二種方法做的,不是好理解;當第i個點加入時,(0 --- i - 1)里面肯定有i喜歡的將他們分到左邊,那剩下的就是i不喜歡的了,也即喜歡i的了,(這里保證每條邊i都會和其他n-1條變有關系,要么喜歡要么不喜歡),對于每次枚舉i,我們在(0~i-1)的范圍看下有多少個i指向的點(剩下的就是指向i的點),同時算下i指向的點的出度和。就可以知道這些 i指向的點 指向 指向i的點(剩下的點)的數目,如果?num * (num - 1) / 2 < sumout 那么就是被指向的點有指出去了,這樣就形成了3元環。?否則,剩下的就是更新下出度即可,繼續執行下一個節點。
View Code #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #define maxn 2007using namespace std;char map[maxn][maxn]; int outd[maxn];int main() {//freopen("d.txt","r",stdin);int t,i,j,n;int cas = 1;scanf("%d",&t);while (t--){printf("Case #%d: ",cas++);scanf("%d",&n);for (i = 0; i < n; ++i)scanf("%s",map[i]);memset(outd,0,sizeof(outd));bool flag = false;for (i = 0; i < n; ++i){int num = 0,out = 0;for (j = 0; j < i; ++j)//枚舉出i指向的點 {if (map[i][j] == '1'){out += outd[j];//記錄i指向的點的初讀num++;outd[i]++;//同時本身的初度累加 }}if ((num- 1)*num/2 < out)//比較 {flag = true;break;}//更新出度for (j = 0; j < i; ++j){if (map[j][i] == '1')outd[j]++;}}if (flag) printf("Yes\n");else printf("No\n");}return 0; }1006 hdu 4325?http://acm.hdu.edu.cn/showproblem.php?pid=4325
題意:
給出每朵花的開花時間段[si,ti],存在又在同一時間段開花的,詢問每個時間點pi幾朵花在開放;
思路:
本來一道很簡單的線段數的成端更新+單點詢問+離散化的題目,可是我在離散化的時候只離散化了輸入的時間段的端點,在詢問時就出了問題,跳了很長時間很是不對,后來把所有的點都離散化后建樹,做操作就簡單的跟屎似的了,沒有構思好就看似是敲代碼。不行啊。。
View Code #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #define maxn 100007 using namespace std;int val[12*maxn],X[3*maxn]; int L[maxn],R[maxn],w[maxn]; int bsearch(int l,int r,int sc) {while (l <= r){int m = (l + r)>>1;if (sc == X[m]) return m;else if (sc < X[m]) r = m - 1;else l = m + 1;}return l; } void pushdown(int rt) {if (val[rt]){val[rt<<1] += val[rt];val[rt<<1|1] += val[rt];val[rt] = 0;} } void update(int L,int R,int sc,int l,int r,int rt) {if (l >= L && r <= R){val[rt] += sc;return;}pushdown(rt);int m = (l + r)>>1;if (L <= m) update(L,R,sc,l,m,rt<<1);if (R > m) update(L,R,sc,m + 1,r,rt<<1|1); } int query(int pos,int l,int r,int rt) {if (l == r){return val[rt];}pushdown(rt);int res = 0;int m = (l + r)>>1;if (pos <= m) res = query(pos,l,m,rt<<1);else res = query(pos,m + 1,r,rt<<1|1);return res; } int main() {int t,i;int n,q;int cas = 1;scanf("%d",&t);while (t--){printf("Case #%d:\n",cas++);scanf("%d%d",&n,&q);int mm = 0;for (i = 0; i < n; ++i){scanf("%d%d",&L[i],&R[i]);X[++mm] = L[i];X[++mm] = R[i];}for (i = 0; i < q; ++i){scanf("%d",&w[i]);X[++mm] = w[i];}sort(X + 1,X + 1 + mm);int m = 1;for (i = 2; i <= mm; ++i){if (X[i] != X[i - 1]) X[++m] = X[i];}memset(val,0,sizeof(val));for (i = 0; i < n; ++i){int l = bsearch(1,m,L[i]);int r = bsearch(1,m,R[i]);update(l,r,1,1,m,1);}for (i = 0; i < q; ++i){int pos = bsearch(1,m,w[i]);printf("%d\n",query(pos,1,m,1));}}return 0; }?
?
?
官方解題報告:http://page.renren.com/601081183/note/863771603?ref=minifeed&sfet=2012&fin=0&ff_id=601081183&feed=page_blog&tagid=863771603&statID=page_601081183_2&level=1
轉載于:https://www.cnblogs.com/E-star/archive/2012/08/01/2619066.html
總結
以上是生活随笔為你收集整理的2012 Multi-University Training Contest 3的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: silverlight之ToolTipS
- 下一篇: HDU 2115 -I Love Thi