1001 質數篩選 判斷公共因子
題意:判斷A進制下的有限小數 能否轉化成B進制下的有限小數。
題解給的是,只需要判斷B中質因子是否包含A中質因子即可。不是很明白,後來問了羣裏的大牛,現在也算明白些了。
整數部分的互相轉換不用考慮,一定可以轉換的,A進制轉化成十進制的小數形式是(1/A + 1/A^2 + 1/A^3 + ... + 1/A^n) 係數不用考慮,想想十進制化二進制的時候是每次都乘以2取整什麼的,所以要化成B進制小數,並且保證最後是有限小數,那麼需要(1/A^x)*B^k 爲整數,()前的係數不影響,一個整數可以分解成p1^a1*p2*a2...pn^an(質因數分解)的形式,所以只要B的質因子包含A的質因子即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1000010;
int isprime[maxn] = {0};
int prime[maxn];
ll ans[maxn];
int main() {
int i , j;
for(i = 2 ; i*i < maxn ; i ++)
if(!isprime[i])
for(j = i+i ; j < maxn ; j += i)
isprime[j] = 1;
int g = 0;
for(i = 2 ; i < maxn ; i ++) {
if(!isprime[i]) prime[g++] = i;
}
int T;
int cas = 1;
scanf("%d",&T);
while(T--) {
ll t = 0;
ll A , B;
cin>>A>>B;
int sus = 1;
for(i = 0 ; prime[i]<=A && prime[i] ; i ++) {
int flag = 0;
if(A%prime[i]==0) {
if(B%prime[i]!=0) {
sus = 0;
break;
}
}
while(A%prime[i]==0) A/=prime[i];
}
if(A!=1 && B%A!=0) sus = 0; //A沒有約到1 但是每次約的時候 B也跟着除了
if(sus) printf("Case #%d: YES\n",cas++);
else printf("Case #%d: NO\n",cas++);
}
}
1005 判環
題意:給出一個有向圖圖,保證兩兩點之間一定有邊,求是否存在三個點的環。
思路:看官方題解。。。沒看明白,後來往上看的什麼判環。。畫了畫,果然,只要圖中有環,那麼一定存在三元環,因爲兩兩點之間必定有邊,可以用4個點5個點試試。所以用拓撲排序判環就行,但是用DFS判環一直TLE、、、
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 2010;
int map[maxn][maxn];
char s[maxn][maxn];
int main() {
int T , cas = 1;
int indegree[maxn];
scanf("%d",&T);
while(T--) {
int n;
memset(indegree , 0 , sizeof(indegree));
scanf("%d",&n);
int i , j;
for(i = 1 ; i <= n ; i ++)
scanf("%s",s[i]+1);
for(i = 1 ; i <= n ; i ++)
for(j = 1 ; j <= n ; j ++) {
map[i][j] = s[i][j] - '0';
if(map[i][j]) {
indegree[j]++;
//printf("%d %d\n",i,j);
}
}
int k , m = 0;
for(i = 1 ; i <= n ; i ++) {
for(j = 1 ; j <= n ; j ++) {
if(indegree[j]==0) {
indegree[j] = -1;//刪點
m++;
for(k = 1 ; k <= n ; k ++) {
if(map[j][k]) {
map[j][k] = 0;
indegree[k]--;
}
}
break;
}
}
}
//printf("%d\n",m);
if(m!=n) printf("Case #%d: Yes\n",cas++);
else printf("Case #%d: No\n",cas++);
}
}
還有一個。。。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 2010;
const int maxm = 2100000;
struct edge{
int v;
int nex;
}e[maxm];
int k , head[maxn];
void addedge(int a , int b) {
e[k].v = b;
e[k].nex = head[a];
head[a] = k++;
}
char s[maxn][maxn];
int indegree[maxn];
int main() {
int T , cas = 1;
scanf("%d",&T);
while(T--) {
int n;
scanf("%d",&n);
for(int i = 1 ; i <= n ; i ++)
scanf("%s",s[i]+1);
int a , b;
k = 1;
memset(head , -1 , sizeof(head));
memset(indegree , 0 , sizeof(indegree));
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= n ; j ++) {
if(s[i][j]-'0'>0) {
a = i;
b = j;
addedge(a , b);
indegree[b]++;
}
}
int flag = 0 , p = 0;
queue<int> q;
for(int i = 1 ; i <= n ; i ++) {
if(indegree[i]==0) {
q.push(i);
p = 1;
}
}
if(!p) {
printf("Case #%d: Yes\n",cas++);
continue;
}
int m = 0;
while(!q.empty()) {
int t = q.front();
q.pop();
m++;
for(int j = head[t] ; j != -1 ; j = e[j].nex) {
int v = e[j].v;
indegree[v]--;
if(indegree[v]==0) q.push(v);
}
}
if(m!=n) printf("Case #%d: Yes\n",cas++);
else printf("Case #%d: No\n",cas++);
}
}
1006 線段樹
題意:給出一些區間代表花開的時間段,詢問的時候給出時間點,問這個時候有多少花是開着的。
思路:線段樹+lazy+離散化
這道題看人人上思路後嘗試着自己搞,也是用的離散化,但是總超時。。。也許寫的也不對,後來就看別人沒有離散化的版本給A了,今天又看到這個
http://www.cnblogs.com/Yu2012/archive/2012/08/09/2630444.html HH版本的線段樹 用的離散化。 發現我寫的還是有毛病,思路不清晰,細節不注意,總之線段樹還是不熟練。。。而且最坑爹的是寫的差不多了,cout ..2000ms+超時 printf直接過。。擦的
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l , m , rt<<1
#define rson m + 1 , r , rt<<1|1
const int maxn = 100100;
int X[maxn<<2];
int li[maxn] , ri[maxn] , qq[maxn];
int add[maxn<<2]; //lazy
int sum[maxn<<2]; //該區間內出現了花開的次數
int ans;
void Pushdown(int rt) { //節點編號 區間長度
if(add[rt]!=0) {
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt];
sum[rt<<1|1] += add[rt];
add[rt] = 0;
//printf("向下更新\n");
}
}
int Bin(int key , int n , int X[]) {
int l = 0;
int r = n - 1;
int m , k = -1;
while(l <= r) {
m = (l + r)>>1;
if(key >= X[m]) {
k = m;
l = m + 1;
} else r = m - 1;
}
return k;
}
void build(int l , int r , int rt) {
add[rt] = 0;
sum[rt] = 0;
if(l == r) return;
int m = (l + r)>>1;
//printf("%d %d %d\n",l,r,rt);
build(lson);
build(rson);
}
void Update(int L , int R , int l , int r , int rt) {
//printf("%d %d %d %d %d\n",L,R,l,r,rt);
if(L<=l && R>=r) {
add[rt] ++;
sum[rt] ++;
return;
}
Pushdown(rt);
int m = (l + r)>>1;
if(m >= L) Update(L , R , lson);
if(m < R) Update(L , R , rson);
}
int Query(int L , int R , int l , int r , int rt) {
if(L <= l && R >= r) {
return sum[rt];
}
Pushdown(rt);
//if(l == r) return sum[rt];
int ret = 0;
int m = (l + r)>>1;
if(m >= L) ret += Query(L , R , lson);
if(m < R) ret += Query(L , R , rson);
return ret;
}
int main() {
int T;
int cas = 1;
scanf("%d",&T);
while(T--) {
int u , q , i;
scanf("%d%d",&u,&q);
int g = 0;
for(i = 0 ; i < u ; i ++) {
scanf("%d%d",&li[i],&ri[i]);
X[g++] = li[i];
X[g++] = ri[i];
}
for(i = 0 ; i < q ; i ++) {
scanf("%d",&qq[i]);
X[g++] = qq[i];
}
sort(X , X + g);
int m = 1;
for(i = 1 ; i < g ; i ++) { //去重
if(X[i]!=X[i-1])
X[m++] = X[i];
}
build(0 , m , 1);
for(i = 0 ; i < u ; i ++) {
int l = Bin(li[i] , m , X);
int r = Bin(ri[i] , m , X);
Update(l , r , 0 , m , 1);
}
int tq;
printf("Case #%d:\n",cas++);
for(i = 0 ; i < q ; i ++) {
ans = 0;
int key = Bin(qq[i] , m , X);
printf("%d\n",Query(key , key , 0 , m , 1)); //就這裏改成cout 超時坑死你!
}
}
}