A. 暑假作业题
大模拟, 字符串读入时要注意前导0
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <climits>
#define MAXN 100005
#define eps 1e-5
#define MOD 1000000009
#define test
#define For(i,m,n) for(int i=(m);i<(n);i++)
#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)
#define rep(i,m,n) for(int i=(m);i<=(n);i++)
#define LL long long
/*author birdstorm*/
using namespace std;
const double pi=acos(-1.0);
template<class T>
inline bool read(T &n){
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
template <class T>
inline void write(T n) {
if(n < 0) {
putchar('-');
n = -n;
}
int len = 0,data[20];
while(n) {
data[len++] = n%10;
n /= 10;
}
if(!len) data[len++] = 0;
while(len--) putchar(data[len]+48);
}
int main()
{
int t;
LL a;
char c[20];
read(t);
while(t--){
scanf("%s",c);
int cnt=strlen(c);
bool flag1w=false, flag1e=false;
bool flagb=false, flagq=false, f3=true;
if(cnt==1&&c[0]=='0') printf("0");
for(int i=0; i<cnt; i++){
int p=cnt-i-1;
bool flag=false;
if(c[i]-'0'){
printf("%d",c[i]-'0');
flag=true;
if(p>=4&&p<8) flag1w=true;
if(p>=13&&p<16) flag1w=true;
if(p>=8) flag1e=true;
}
else{
if(c[i+1]-'0'&&p>4&&p<8&&flag1w) printf("0");
else if(c[i+1]-'0'&&p>13&&p<16&&flag1w) printf("0");
else if(c[i+1]-'0'&&(p==1||p==5||p==9||p==13)) printf("0");
else if(c[i+1]-'0'&&(p==2||p==6||p==10||p==14)) printf("0");
else if(c[i+1]-'0'&&(p==3||p==7||p==11||p==15)) printf("0");
//continue;
}
if(p==13) flag1w=false;
if(!flag){
if(flag1w&&p==4) printf("W"),flag1w=false;
if(flag1e&&p==12) printf("W"),flag1w=false;
if(flag1e&&p==8) printf("E"),flag1e=false;
continue;
}
if(p==1||p==5||p==9||p==13) printf("S");
if(p==2||p==6||p==10||p==14) printf("B");
if(p==3||p==7||p==11||p==15) printf("Q");
if(p==4||p==12) printf("W");
if(p==8) printf("E");
}
puts("");
}
return 0;
}
B. 最长数链
暴力使用dfs搜索
正确的姿势是发现数链中的数只可能是2和3的倍数, 大大降低复杂度, 可以log(n)求出
这个姿势有点慢了= =
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <climits>
#define MAXN 100005
#define eps 1e-5
#define MOD 1000000009
#define test
#define For(i,m,n) for(int i=(m);i<(n);i++)
#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)
#define rep(i,m,n) for(int i=(m);i<=(n);i++)
#define LL long long
/*author birdstorm*/
using namespace std;
const double pi=acos(-1.0);
template<class T>
inline bool read(T &n){
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
template <class T>
inline void write(T n) {
if(n < 0) {
putchar('-');
n = -n;
}
int len = 0,data[20];
while(n) {
data[len++] = n%10;
n /= 10;
}
if(!len) data[len++] = 0;
while(len--) putchar(data[len]+48);
}
int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43};
int sta[MAXN],stac[MAXN];
int dfs(int g,int pos,int cnt)
{
int ans=-1;
if(g==1) return cnt;
else{
For(i,pos,13){
if(g%prime[i]==0){
int len=dfs(g/prime[i],i,cnt+1);
//if(len==-1) break;
if(ans<=len){
ans=len;
sta[cnt+1]=prime[i];
}
}
}
}
return ans;
}
int ans;
int main()
{
int a;
while(read(a)){
ans=0;
int t;
memset(sta,0,sizeof sta);
for(int i=a/2+1;i<=a;i++){
int len=dfs(i,0,0);
if(len>=ans){
ans=len;
For(j,0,ans+1) stac[j]=sta[j];
t=i;
}
}
//ans=dfs(t,0,0);
//For(j,0,ans+1) stac[j]=sta[j];
int g=1;
printf("1");
for(int i=ans;i>=1;i--){
printf(" %d",g*stac[i]);
g*=stac[i];
if(g==t) break;
}
puts("");
}
return 0;
}
C. 三角形的传说
可以证明只有三种可能解, 判断即可
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <climits>
#define MAXN 100005
#define eps 1e-5
#define MOD 1000000009
#define test
#define For(i,m,n) for(int i=(m);i<(n);i++)
#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)
#define rep(i,m,n) for(int i=(m);i<=(n);i++)
#define LL long long
/*author birdstorm*/
using namespace std;
const double pi=acos(-1.0);
template<class T>
inline bool read(T &n){
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
template <class T>
inline void write(T n) {
if(n < 0) {
putchar('-');
n = -n;
}
int len = 0,data[20];
while(n) {
data[len++] = n%10;
n /= 10;
}
if(!len) data[len++] = 0;
while(len--) putchar(data[len]+48);
}
int main()
{
int t, cs=1;
int m, q;
scanf("%d",&t);
while(t--){
read(m),read(q);
printf("Case %d: ",cs++);
int ans=10000000;
if(m%2==0){
if(m>=q*2){
ans=2*q+2*m;
}
else ans=2*q+m;
}
else{
if(2*q>m){
ans=2*q+m;
}
else ans=2*q+2*m;
}
if(q<=1) ans=3*m+2*q;
printf("%d\n",ans);
}
return 0;
}
D. 帮帮小叮当
dp/图论
dp的正确性: 由于是从确定状态转移至不确定状态, 所以dp的结果正确.
图论可采用SPFA, 速度也不慢.
可是使用dij+堆优化的话似乎不能在时限内通过, 原因不明
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <climits>
#define MAXN 100005
#define eps 1e-5
#define MOD 1000000007
#define INF 1000000007
#define test
#define For(i,m,n) for(int i=(m);i<(n);i++)
#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)
#define rep(i,m,n) for(int i=(m);i<=(n);i++)
#define LL long long
/*author birdstorm*/
using namespace std;
const double pi=acos(-1.0);
template<class T>
inline bool read(T &n){
T x = 0, tmp = 1; char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
template <class T>
inline void write(T n) {
if(n < 0) {
putchar('-');
n = -n;
}
int len = 0,data[20];
while(n) {
data[len++] = n%10;
n /= 10;
}
if(!len) data[len++] = 0;
while(len--) putchar(data[len]+48);
}
int dp[MAXN], a[MAXN];
int main()
{
int n, m;
while(read(n)&&read(m),n||m){
For(i,0,n) read(a[i]);
int ans=INF;
dp[0]=a[0]-1;
For(i,1,n) dp[i]=min(dp[i-1]+1,i+a[i]-1);
for(int i=n-2;i>=0;i--) dp[i]=min(dp[i],dp[i+1]+1);
For(i,0,n) ans=min(ans,dp[i]+n-i+m-a[i]-1);
printf("%d\n",ans);
}
return 0;
}
E. hiyot的神题
线段树维护区间gcd, 然后使用容斥原理计算答案.
考虑到1000以内的数分解素数后最多只有五个, 也可以暴力手算容斥.
比如:
LL solve(LL a, LL m)
{
int sz=g[a].size();
LL ret=0;
if(sz==1) ret=m-m/g[a][0];
else if(sz==2) ret=m-m/g[a][0]-m/g[a][1]+m/(g[a][0]*g[a][1]);
else if(sz==3){
LL a1=g[a][0], a2=g[a][1], a3=g[a][2];
ret=m-m/a1-m/a2-m/a3+m/(a1*a2)+m/(a1*a3)+m/(a2*a3)-m/(a1*a2*a3);
}
else if(sz==4){
LL a1=g[a][0], a2=g[a][1], a3=g[a][2], a4=g[a][3];
ret=m-m/a1-m/a2-m/a3-m/a4+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a2*a3)+m/(a2*a4)+m/(a3*a4)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a3*a4)-m/(a2*a3*a4)+m/(a1*a2*a3*a4);
}
else if(sz==5){
LL a1=g[a][0], a2=g[a][1], a3=g[a][2], a4=g[a][3], a5=g[a][4];
ret=m-m/a1-m/a2-m/a3-m/a4-m/a5+m/(a1*a2)+m/(a1*a3)+m/(a1*a4)+m/(a1*a5)+m/(a2*a3)+m/(a2*a4)+m/(a2*a5)+m/(a3*a4)+m/(a3*a5)+m/(a4*a5)-m/(a1*a2*a3)-m/(a1*a2*a4)-m/(a1*a2*a5)-m/(a1*a3*a4)-m/(a1*a3*a5)-m/(a1*a4*a5)-m/(a2*a3*a4)-m/(a2*a3*a5)-m/(a2*a4*a5)-m/(a3*a4*a5)+m/(a1*a2*a3*a4)+m/(a1*a2*a3*a5)+m/(a1*a2*a4*a5)+m/(a1*a3*a4*a5)+m/(a2*a3*a4*a5)-m/(a1*a2*a3*a4*a5);
}
return ret-1;
}
这里推荐的是比较优美的dfs姿势
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <vector>
#include <algorithm>
#define MAXN 10005
#define For(i,m,n) for(int i=(m);i<(n);i++)
#define LL long long
using namespace std;
LL prime[]={2,3,5,7,11,13,17,19,23,29,31};
struct node{
int left, right;
LL gcd;
}arr[MAXN<<4];
LL num[MAXN], c;
LL gcd(LL a, LL b)
{
return b==0?a:gcd(b,a%b);
}
void build(int idx, int l, int r){
arr[idx].left = l, arr[idx].right = r;
arr[idx].gcd = 0;
if(l == r){
arr[idx].gcd = num[l];
return;
}
int mid = (l + r) >> 1;
build(idx << 1, l, mid);
build(idx << 1 | 1, mid + 1, r);
arr[idx].gcd = gcd(arr[idx << 1].gcd , arr[idx << 1 | 1].gcd);
}
LL ans;
bool query(int idx, int l, int r){
if(arr[idx].right < l||arr[idx].left > r) return false;
if(arr[idx].left >= l&&arr[idx].right <= r){
ans=gcd(ans,arr[idx].gcd);
return true;
}
query(idx << 1, l, r);
query(idx << 1 | 1, l, r);
return true;
}
void update(int idx, int val, int pos)
{
int l = arr[idx].left, r = arr[idx].right;
if(l == r){
arr[idx].gcd=val;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(idx << 1, val, pos);
else update(idx << 1 | 1, val, pos);
arr[idx].gcd = gcd(arr[idx<<1].gcd, arr[idx<<1|1].gcd);
}
vector<LL> g[1111], v;
void init()
{
for(LL i=2; i<=1000; ++i){
g[i].clear();
LL tmp=i;
For(j,0,11){
if(tmp%prime[j]==0){
while(tmp%prime[j]==0) tmp/=prime[j];
g[i].push_back(prime[j]);
}
}
if(tmp!=1) g[i].push_back(tmp);
}
}
LL dfs(int pos, int sz, LL a, LL m)
{
LL ret=0;
For(i,pos,sz){
ret+=m/g[a][i]-dfs(i+1,sz,a,m/g[a][i]);
}
return ret;
}
int main()
{
int t, n, q, l, r;
LL g1, m;
init();
while(~scanf("%d",&n)){
scanf("%lld%d",&m,&q);
For(i,1,n+1) scanf("%lld",&num[i]);
build(1,1,n);
int o;
while(q--){
scanf("%d%d",&o,&l);
if(o==1){
scanf("%d",&r);
ans=num[l];
query(1,l,r);
if(ans==1) printf("-1\n");
else{
int sz=g[ans].size();
LL ret=m-1-dfs(0,sz,ans,m);
printf("%lld\n",ret);
}
}
else{
scanf("%lld",&g1); num[l]=g1;
update(1,g1,l);
}
}
}
return 0;
}