kuangbin数论题单

没几道题,却做了很长时间。有几个很水的题,但大部分质量很高,尤其是最后做的三四个题,把我写吐了。
题单地址:[kuangbin带你飞]专题1-23

LightOJ 1370 Bi-shoe and Phi-shoe

筛法得到欧拉函数的值

代码

#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
int euler[2000005];
void getEuler(int n){
	euler[1] = 1;
	for(int i=2; i<=n; i++){
		if(!euler[i]){
			for(int j=i; j<=n; j += i){
				if(!euler[j]){
					euler[j] = j;
				}
				euler[j] = euler[j]/i*(i-1);
			}
		}
	}
}
int mp[2000005];
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	getEuler(2000005);
	memset(mp, INF, sizeof(mp));
	FOR(i, 1, 2000005){
		if(euler[i]<=2000000){
			mp[euler[i]] = min(mp[euler[i]], i);
		}
	}
	ROF(i, 1500004, 1){
		mp[i] = min(mp[i], mp[i+1]);
	}
	mp[1] = 2;
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ll ans = 0;
		int n;
		cin >> n;
		int t;
		FOR(i, 1, n){
			cin >>t;
			//cout << t << " " << mp[t] << endl;
			ans += mp[t];
		}
		printf("Case %d: %lld Xukha\n",tt,ans);
	}
	return 0;
}

LightOJ 1341 Aladdin and the Flying Carpet

网上很多代码对\(1-b\)进行循环,复杂度是不正确的。由于\(a\)的素因数最多只有\(\log_{2}a\)个。设\(a=p_1^{k_1}p_1^{k_2}...p_1^{k_n}\),由基本不等式\(k_1k_2..k_n<=(\frac{k_1+k_2...+k_n}{n})^2<=(\frac{\log_{2}a}{n})^2\),可知a的所有素因数个数的乘积不会太大,所以可以用\(dfs\)枚举\(a\)所有可能的因数。

代码

#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int MAXN=1000000;
// 素数筛选
int prime[MAXN+1];
void getPrime(){
	for(int i=2; i<=MAXN; i++){
		if(!prime[i]) prime[++prime[0]]=i;
		for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++){
			prime[prime[j]*i] = 1;
			if(i%prime[j]==0) break;
		}
	}
}
// 合数分解
ll factor[100][2];
int factCnt;
void getFactors(ll x){
	ll temp = x;
	factCnt = 0;
	for(int i=1; i<=prime[0] && prime[i]<=temp/prime[i]; i++){ //cout << i << " " << temp << endl;
		factor[factCnt][1] = 0;
		if(temp%prime[i]==0){
			factor[factCnt][0] = prime[i];
			while(temp%prime[i]==0){
				factor[factCnt][1]++;
				temp /= prime[i];
			}
			factCnt++;
		}
	}
	if(temp!=1){
		factor[factCnt][0] = temp;
		factor[factCnt++][1] = 1;
	}
}
ll a, b;
ll ans;
void dfs(ll now, ll tot){
	if(now==factCnt){
		if(tot*tot!=a && tot>=b && a/tot>=b) {
			ans++;
		}
		return;
	}
	ll temp = 1;
	FOR(i, 0, factor[now][1]){
		tot *= temp;
		dfs(now+1, tot);
		tot /= temp;
		temp *= factor[now][0];
	}
	return;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	getPrime();
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ans = 0;
		cin >> a >> b;
		getFactors(a);
		dfs(0, 1);
		ans /= 2;
		printf("Case %d: %d\n", tt, ans);
	}
	return 0;
}

LightOJ 1336 Sigma Function

将题目所给公式化简为\(\sigma(n)=(1+p_1+..+p_1^{e_1})(1+p_2+..+p_2^{e_2})...(1+p_k+..+p_k^{e_k})\),如果要让\(\sigma(n)\)为奇数,由于当\(p_k\)为2时,\((1+p_k+..+p_k^{e_k})\)一定为奇数,所以剩下的素因子的指数应该都是偶数,这样当2的指数也是偶数时,\(n\)是某个数的平方。当2的指数是奇数时,如果其余素因子的指数是偶数,应该有\(n/2\)是某个数的平方。综上\(\sigma(n)\)是奇数的条件就是\(n\)是某个数的平方或\(n/2\)是某个数的平方。这个题即输出\(n-\sqrt{n}-\sqrt{n/2}\)

代码

#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=100000;
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	int t;
	cin >> t;
	FOR(i, 1, t){
		ll n;
		cin >> n;
		n -= (ll)sqrt(n)+(ll)sqrt(n/2);
		cout << "Case " << i << ": " << n << endl;
	}
	return 0;
}

LightOJ 1282 Leading and Trailing

后三位用快速幂对\(n^k\)模1000就可以了。计算前三位时把原数变形为\(n^k=10^{\log_{10}a^k}=10^{k\log_{10}a}\),用\(x,y\)表示\(k\log_{10}a\)的整数部分与小数部分,可得\(n^k=10^{x+y}=10^x*10^y\),则\(n^k\)的位数是由\(10^x\)决定的,各位数字是由\(10^y\)决定的,而\(0\leq y<1\),所以\(1\leq 10^y<10\)\(10^y *100\)的整数部分就是\(n^k\)的前三位。

代码

#define LOCAL0
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=100000;
//pow(x,n)%mod O(logn)
ll mod_pow(ll x,ll n,ll mod)
{
    ll res=1;
    while(n>0){
        if(n&1) res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ll n, k;
		cin >> n >> k;
		ll ans2 = mod_pow(n, k, 1000);
		double ans1 = k*log10(n);
		ans1 = fmod(ans1, 1);
		cout << "Case " << tt << ": " << (int)(pow(10, ans1)*100) << " ";
		cout << setw(3) << setfill('0') << ans2 << endl;
	}
	return 0;
}

LightOJ 1259 Goldbach`s Conjecture

把1e7以内的素数先筛出来,之后每个数枚举一下就行了。

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
//n以内素数个数
int prime[maxn];
bool is_prime[maxn+1];
int sieve(int n){
    int p=0;
    for(int i=0;i<=n;i++) is_prime[i]=true;
    is_prime[0]=is_prime[1]=false;
    for(int i=2;i<=n;i++){
        if(is_prime[i]){
            prime[p++]=i;
            for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
        }
    }
    return p;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	int T;
	cin >> T;
	int all = sieve(10000000);
	FOR(tt, 1, T){
		int x;
		cin >> x;
		int ans = 0;
		for(int i=0; i<all; i++){
			if(prime[i]>x/2) break;
			if(is_prime[x-prime[i]]) ans++;
		}
		cout << "Case " << tt << ": " << ans << endl;
	}
	return 0;
}

LightOJ 1245 Harmonic Number (II)

数论分块

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ll n;
		cin >> n;
		ll ans = 0;
		for(ll l=1, r; l<=n; l=r+1){
			r = n/(n/l);
			ans += (r-l+1)*(n/l);
		}
		printf("Case %d: %lld\n", tt, ans);
	}
	return 0;
}

LightOJ 1236 Pairs Forming LCM

\[ \begin{aligned} &设\,\,a=p_1^{k_{a1}}p_2^{k_{a2}}...p_s^{k_{as}},\,\,b=p_1^{k_{b1}}p_2^{k_{b2}}...p_s^{k_{bs}}\\ &有\,\,gcd(a,b)=p_1^{min(k_{a1},k_{b1})}p_2^{min(k_{a2},k_{b2})}...p_s^{min(k_{as},k_{bs})}\\ &\quad lcm(a,b)=p_1^{max(k_{a1},k_{b1})}p_2^{max(k_{a2},k_{b2})}...p_s^{max(k_{as},k_{bs})}\\ \end{aligned} \]

\(n=p_1^{k_1}p_2^{k_2}...p_m^{k_m}\),由上述式子不难得出\(\forall 1\leq i,j\leq n\),使\(lcm(i,j)=n\)的方案数有\(sum=(2*k_1+1)(2*k_2+1)...(2*k_m+1)\)种,而本题要求\(1\leq i\leq j\leq n\),所以方案数为\((sum+1)/2\)(分子加一是考虑到\(i=j\)的情况)

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
int prime[maxn+1];
void getPrime(){
	memset(prime, 0 ,sizeof(prime));
	for(int i=2; i<=maxn; i++){
		if(!prime[i]) prime[++prime[0]] = i;
		for(int j=1; j<=prime[0]&&prime[j]<=maxn/i; j++){
			prime[prime[j]*i] = 1;
			if(j%prime[j]==0) break;
		}
	}
}
ll factor[100][2];
int factCnt;
int getFactors(ll x){
	factCnt = 0;
	ll temp = x;
	for(int i=1; prime[i]<=temp/prime[i] && i<=prime[0]; i++){
		factor[factCnt][1] = 0;
		if(temp%prime[i]==0){
			factor[factCnt][0] = prime[i];
			while(temp%prime[i]==0){
				factor[factCnt][1]++;
				temp /= prime[i];
			}
			factCnt++;
		}
	}
	if(temp!=1){
		factor[factCnt][0] = temp;
		factor[factCnt++][1] = 1;
	}
	return factCnt;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	getPrime();
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ll n;
		cin >> n;
		ll ans = 1;
		getFactors(n);
		for(int i=0; i<factCnt; i++){
			ans *= 2*factor[i][1]+1;
		}
		ans = (ans+1)/2;
		printf("Case %d: %I64d\n", tt, ans);
	}
	return 0;
}

LightOJ 1234 Harmonic Number

直接暴力可以跑出来,但是数组开不到1e8,可以每50个数分一块,这样每次查询最多再跑49次就可以了。

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
double sum[20000005];
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	double temp;
	FOR(i, 1, 100000000){
		temp = 0;
		FOR(j, 1, 50){
			temp += 1/(double)i;
			i++;
		}
		i--;
		sum[i/50] = sum[i/50-1]+temp;
	}
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ll n;
		cin >> n;
		double ans = sum[n/50];
		ROF(i, n, n-n%50+1) ans += 1/(double)i;
		printf("Case %d: %.10f\n", tt, ans);
	}
	return 0;
}

LightOJ 1220 Mysterious Bacteria

唯一分解定理后取指数项最小值即可。注意当n为负数时,答案一定为奇数,所以要将结果一直除二直到变为奇数。

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=10000005;
int prime[maxn+1];
void getPrime(){
	memset(prime, 0 ,sizeof(prime));
	for(int i=2; i<=maxn; i++){
		if(!prime[i]) prime[++prime[0]] = i;
		for(int j=1; j<=prime[0]&&prime[j]<=maxn/i; j++){
			prime[prime[j]*i] = 1;
			if(j%prime[j]==0) break;
		}
	}
}
ll factor[100][2];
int factCnt;
int getFactors(ll x){
	factCnt = 0;
	ll temp = x;
	for(int i=1; prime[i]<=temp/prime[i] && i<=prime[0]; i++){
		factor[factCnt][1] = 0;
		if(temp%prime[i]==0){
			factor[factCnt][0] = prime[i];
			while(temp%prime[i]==0){
				factor[factCnt][1]++;
				temp /= prime[i];
			}
			factCnt++;
		}
	}
	if(temp!=1){
		factor[factCnt][0] = temp;
		factor[factCnt++][1] = 1;
	}
	return factCnt;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	getPrime();
	int T;
	cin >> T;
	FOR(tt, 1, T){
		ll n;
		cin >> n;
		getFactors(abs(n));
		int ans = INF;
		FOR(i, 0, factCnt-1){
			ans = min(1ll*ans, factor[i][1]);
		}
		if(n<0) while(ans%2==0) ans /= 2;
		printf("Case %d: %d\n", tt, ans);
	}
	return 0;
}

LightOJ 1214 Large Division

高精度模板

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 500;
struct bign{
    int d[maxn], len;

    void clean() { while(len > 1 && !d[len-1]) len--; }

    bign()          { memset(d, 0, sizeof(d)); len = 1; }
    bign(int num)   { *this = num; }
    bign(char* num) { *this = num; }
    bign operator = (const char* num){
        memset(d, 0, sizeof(d)); len = strlen(num);
        for(int i = 0; i < len; i++) d[i] = num[len-1-i] - '0';
        clean();
        return *this;
    }
    bign operator = (int num){
        char s[20]; sprintf(s, "%d", num);
        *this = s;
        return *this;
    }

    bign operator + (const bign& b){
        bign c = *this; int i;
        for (i = 0; i < b.len; i++){
            c.d[i] += b.d[i];
            if (c.d[i] > 9) c.d[i]%=10, c.d[i+1]++;
        }
        while (c.d[i] > 9) c.d[i++]%=10, c.d[i]++;
        c.len = max(len, b.len);
        if (c.d[i] && c.len <= i) c.len = i+1;
        return c;
    }
    bign operator - (const bign& b){
        bign c = *this; int i;
        for (i = 0; i < b.len; i++){
            c.d[i] -= b.d[i];
            if (c.d[i] < 0) c.d[i]+=10, c.d[i+1]--;
        }
        while (c.d[i] < 0) c.d[i++]+=10, c.d[i]--;
        c.clean();
        return c;
    }
    bign operator * (const bign& b)const{
        int i, j; bign c; c.len = len + b.len;
        for(j = 0; j < b.len; j++) for(i = 0; i < len; i++)
            c.d[i+j] += d[i] * b.d[j];
        for(i = 0; i < c.len-1; i++)
            c.d[i+1] += c.d[i]/10, c.d[i] %= 10;
        c.clean();
        return c;
    }
    bign operator / (const bign& b){
        int i, j;
        bign c = *this, a = 0;
        for (i = len - 1; i >= 0; i--)
        {
            a = a*10 + d[i];
            for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
            c.d[i] = j;
            a = a - b*j;
        }
        c.clean();
        return c;
    }
    bign operator % (const bign& b){
        int i, j;
        bign a = 0;
        for (i = len - 1; i >= 0; i--)
        {
            a = a*10 + d[i];
            for (j = 0; j < 10; j++) if (a < b*(j+1)) break;
            a = a - b*j;
        }
        return a;
    }
    bign operator += (const bign& b){
        *this = *this + b;
        return *this;
    }

    bool operator <(const bign& b) const{
        if(len != b.len) return len < b.len;
        for(int i = len-1; i >= 0; i--)
            if(d[i] != b.d[i]) return d[i] < b.d[i];
        return false;
    }
    bool operator >(const bign& b) const{return b < *this;}
    bool operator<=(const bign& b) const{return !(b < *this);}
    bool operator>=(const bign& b) const{return !(*this < b);}
    bool operator!=(const bign& b) const{return b < *this || *this < b;}
    bool operator==(const bign& b) const{return !(b < *this) && !(b > *this);}

    string str() const{
        char s[maxn]={};
        for(int i = 0; i < len; i++) s[len-1-i] = d[i]+'0';
        return s;
    }
};
istream& operator >> (istream& in, bign& x)
{
    string s;
    in >> s;
    x = s.c_str();
    return in;
}
ostream& operator << (ostream& out, const bign& x)
{
    out << x.str();
    return out;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	int T;
	cin >> T;
	FOR(tt, 1, T){
	    bign a,b;
		cin >> a >> b;
		if(a.d[a.len-1]<0) a.d[a.len-1] = 0, a.len--;
		if(b.d[b.len-1]<0) b.d[b.len-1] = 0, b.len--;
		if(a%b!=bign(0)) printf("Case %d: not divisible\n", tt);
		else printf("Case %d: divisible\n", tt);
	}
	return 0;
}

LightOJ 1213 Fantasy of a Summation

推式子,\(res=kn^{k-1}sum\)

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
// const ll mod = 1e9+7;
const int maxn = 500005;
int casecnt;
//pow(x,n)%mod O(logn)
ll mod_pow(ll x,ll n,ll mod)
{
    ll res=1;
    while(n>0){
        if(n&1) res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    int T;
    cin >> T;
    while(T--){
        ll n, k, mod, sum = 0;
        cin >> n >> k >> mod;
        FOR(i, 1, n){
            ll x;
            cin >> x;
            sum = (sum+x)%mod;
        }
        sum = mod_pow(n, k-1, mod)*k%mod*sum%mod;
        printf("Case %d: %lld\n", ++casecnt, sum);
    }
	return 0;
}

LightOJ 1197 Help Hanzo

区间素数模板

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000005;
int casecnt;
int prime[maxn+1];
void getPrime(){
	memset(prime, 0 ,sizeof(prime));
	for(int i=2; i<=maxn; i++){
		if(!prime[i]) prime[++prime[0]] = i;
		for(int j=1; j<=prime[0]&&prime[j]<=maxn/i; j++){
			prime[prime[j]*i] = 1;
			if(j%prime[j]==0) break;
		}
	}
}
bool notprime[maxn];
int prime2[maxn];
void getPrime2(int l, int r){
    memset(notprime, false, sizeof(notprime));
    if(l<2) l = 2;
    for(int i=1; i<=prime[0]&&(ll)prime[i]*prime[i]<=r; i++){
        int s = l/prime[i]+(l%prime[i]>0);
        if(s==1) s=2;
        for(int j=s; (ll)j*prime[i]<=r; j++){
            if((ll)j*prime[i]>=l){
                notprime[j*prime[i]-l] = true;
            }
        } 
    }
    prime2[0] = 0;
    for(int i=0; i<=r-l; i++){
        if(!notprime[i]){
            prime2[++prime2[0]] = i+l;
        }
    }
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    getPrime();
    int T;
    cin >> T;
    while(T--){
        int l, r;
        cin >> l >> r;
        getPrime2(l, r);
        printf("Case %d: %d\n", ++casecnt, prime2[0]);
    }
	return 0;
}

LightOJ 1138 Trailing Zeroes (III)

\(n!\)后几位中0的个数其实就是\(n!\)因数中\(5\)的个数,不难推出对于一个确定的n,\(n!\)中后几位0的个数为\(\frac{n}{5}+\frac{n}{5^2}+\frac{n}{5^3}+...\)

二分答案即可

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000005;
int casecnt;
ll fun(ll m){
    ll temp = 0;
    while(m){
        temp += m;
        m /= 5; 
    }
    return temp;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    int T;
    cin >> T;
    while(T--){
        ll n;
        cin >> n;
        ll l = 0, r = 1e8;
        while(r-l>1){
            ll mid = (l+r)>>1;
            if(fun(mid)>n) r = mid;
            else l = mid;
        }
        cout << "Case " << ++casecnt << ": ";
        if(fun(l)==n) cout << 5*l << endl;
        else cout << "impossible\n";
    }
	return 0;
}

UVA 11426 GCD - Extreme (II)

\[ \begin{aligned} &\sum_{i=1}^n\sum_{j=1}^ngcd(i,j)\\ =&\sum_{k=1}^nk\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=k]\\ =&\sum_{k=1}^nk\sum_{i=1}^{n/k}\sum_{j=1}^{n/k}[gcd(i,j)=1]\\ =&\sum_{k=1}^nk\sum_{i=1}^{n/k}\sum_{j=1}^{n/k}\sum_{m|gcd(i,j)}\mu(m)\\ =&\sum_{k=1}^nk\sum_{m=1}^{n}\mu(m)*\frac{n}{km}*\frac{n}{km}\\ =&\sum_{D=1}^n\sum_{k|D}k*\mu(\frac{D}{m})*\frac{n}{D}*\frac{n}{D}\\ =&\sum_{D=1}^n\psi(D)*\frac{n}{D}*\frac{n}{D}\\ \end{aligned} \]

筛出欧拉函数后分块计算即可

代码

#define LOCAL
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1000005;
// 筛法
int euler[4000005];
void getEuler(int n){
	euler[1] = 1;
	for(int i=2; i<=n; i++){
		if(!euler[i]){
			for(int j=i; j<=n; j += i){
				if(!euler[j]){
					euler[j] = j;
				}
				euler[j] = euler[j]/i*(i-1);
			}
		}
	}
}
ll sum[4000005];
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    getEuler(4000002);
    FOR(i, 1, 4000001) sum[i] = sum[i-1]+euler[i];
    ll n;
    while(cin >> n && n){
        ll ans = 0;
        for(int l=1, r; l<=n; l=r+1){
            r = n/(n/l);
            ans += (sum[r]-sum[l-1])*(n/l)*(n/l);
        }
        ans = (ans-n*(n+1)/2)/2;
        cout << ans << endl;
    }
	return 0;
}

POJ 1061 青蛙的约会

题目即求\(x-y+p(m-n)=qL\),转化为\((m-n)x+Ly=y-x\quad(m>n)\)形式用\(exgcd\)求出x的最小正整数解即可。

代码

#define LOCAL
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=1005;
//返回值是gcd(a,b) x<=a,y<=b
ll extgcd(ll a,ll b,ll &x,ll &y)
{
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else{
        x=1;y=0;
    }
    return d;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    ll x, y, m, n, l;
    cin >> x >> y >> m >> n >> l;
    ll p, q, d;
    if(m<n){
        swap(x, y);
        swap(m, n);
    }
    d = extgcd(m-n, l, p, q);
    if((y-x)%d) cout << "Impossible\n";
    else{
        p *= (y-x)/d;
        p %= l/d;
        p = (p+l/d)%(l/d);
        cout << p << endl;
    }    
    return 0;
}

POJ 2115 C Looooops

和上一个题差不多,注意直接使用\(1<<k\)会造成溢出。

代码

#define LOCAL
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <iomanip>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn=1005;
//返回值是gcd(a,b) x<=a,y<=b
ll extgcd(ll a,ll b,ll &x,ll &y)
{
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else{
        x=1;y=0;
    }
    return d;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    ll a, b, c, k;
    while(cin >> a >> b >> c >> k){
        if(a+b+c+k==0) break;
        ll m = (1ll<<k);
        ll x, y;
        ll d = extgcd(c, m, x, y);
        if((b-a)%d){
            cout << "FOREVER\n";
        }
        else{
            x *= (b-a)/d;
            x %= m/d;
            x = (x+m/d)%(m/d);
            cout << x << endl;
        }
    }
    return 0;
}

HDU 2161 Primes

注意n小于等于零时结束输入

代码

#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
//n以内素数个数
const int maxn=1000000;
int prime[maxn];
bool is_prime[maxn+1];
int sieve(int n){
    int p=0;
    for(int i=0;i<=n;i++) is_prime[i]=true;
    is_prime[0]=is_prime[1]=false;
    for(int i=2;i<=n;i++){
        if(is_prime[i]){
            prime[p++]=i;
            for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
        }
    }
    return p;
}

int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    sieve(100000);
    is_prime[2] = false;
    int T = 0;
    int n;
    while(cin >> n && n>0){
        if(is_prime[n]) printf("%d: yes\n", ++T);
        else printf("%d: no\n", ++T);
    }
    return 0;
}

UVA 11827 Maximum GCD

数论题单的题考输入,就挺离谱的

代码

#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (int i=a; i<=(b); i++)
#define ROF(i, a, b) for (int i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;

int gcd(int a, int b){
    return b==0? a: gcd(b, a%b);
}
char s[300000];
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    int T;
    cin >> T;
    getchar();
    while(T--){
        int ans = 0;
        int a[105];
        int m = 0;
        gets(s);
        for(int i=0; i<(int)strlen(s); i++){
            int sum = 0;
            if(isdigit(s[i])){
                while(isdigit(s[i])){
                    sum = sum*10 + s[i] - '0';
                    i++;
                }
                a[++m] = sum; 
            }
            
        }
        FOR(i, 1, m){
            FOR(j, 1, m){
                if(i!=j){
                    ans = max(ans, gcd(a[i], a[j]));
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}

SGU 106 The equation

扩欧求一组解后,根据其解集的形式,解出来两个\(k\)的范围,取个交集就可以了

代码

#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
//返回值是gcd(a,b) x<=a,y<=b
ll extgcd(ll a,ll b,ll &x,ll &y)
{
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else{
        x=1;y=0;
    }
    return d;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    ll a, b, c;
    ll l1, l2, r1, r2, L1, L2, R1, R2;
    L1 = L2 = -INF;
    R1 = R2 = INF;
    cin >> a >> b >> c;
    cin >> l1 >> r1 >> l2 >> r2;
    if(a==0 && b==0){
        if(c==0) cout << (r1-l1+1)*(r2-l2+1);
        else cout << 0;
        cout << endl;
        return 0;
    }
    ll x, y;
    c *= -1;
    ll d = extgcd(a, b, x, y);
    if(c%d){
        cout << 0;
        return 0;
    }
    x *= c/d;
    y *= c/d;
    b /= d;
    a /= d;
    if(b>0){
        L1 = ceil(1.0*(l1-x)/b);
        R1 = floor(1.0*(r1-x)/b);
    } 
    else if(b<0){
        R1 = floor(1.0*(l1-x)/b);
        L1 = ceil(1.0*(r1-x)/b);
    }
    if(a>0){
        L2 = ceil(1.0*(l2-y)/a);
        R2 = floor(1.0*(r2-y)/a);
    }
    else if(a<0){
        R2 = floor(1.0*(l2-y)/a);
        L2 = ceil(1.0*(r2-y)/a);
    }
    if(a){
        swap(L2, R2);
        L2 *= -1;
        R2 *= -1;
    }
    l1 = max(L1, L2);
    r1 = min(R1, R2);
    if(l1>r1) cout << 0 << endl;
    else cout << r1-l1+1 << endl;
    return 0;
}

POJ 2478 Farey Sequence

欧拉函数

代码

#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
// 筛法
int euler[1000005];
ll sum[1000005];
void getEuler(int n){
	euler[1] = 1;
	for(int i=2; i<=n; i++){
		if(!euler[i]){
			for(int j=i; j<=n; j += i){
				if(!euler[j]){
					euler[j] = j;
				}
				euler[j] = euler[j]/i*(i-1);
			}
		}
	}
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    getEuler(1000005);
    FOR(i, 2, 1000000){
        sum[i] = sum[i-1]+euler[i];
    }
    int n;
    while(cin >> n && n){
        cout << sum[n] << endl;
    }
    return 0;
}

UVA 11752 The Super Powers

这个处理精度好恶心。。

代码

#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef unsigned long long ll;
const ll mod = 1e9+7;
//n以内素数个数
const int maxn=1000000;
int prime[maxn];
bool is_prime[maxn+1];
int sieve(int n){
    int p=0;
    for(int i=0;i<=n;i++) is_prime[i]=true;
    is_prime[0]=is_prime[1]=false;
    for(int i=2;i<=n;i++){
        if(is_prime[i]){
            prime[p++]=i;
            for(int j=2*i;j<=n;j+=i) is_prime[j]=false;
        }
    }
    return p;
}
vector<ll> ans;
map<ll, bool> ok;
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    sieve(1000005);
    ans.pb(1);
    ll mx = 1ll*18446744073709551615;
    for(ll i=2; i<=(1<<16); i++){
        ll base = i;
        for(int j=2; j<=100; j++){
            base *= i;
            if(is_prime[j]){
                if(base>mx/i) break;
                continue;
            }
            if(!ok[base]){
                ok[base] = true;
                ans.pb(base);
                
            }
            if(base>mx/i) break;
        }
    }
    sort(ALL(ans));
    for(auto x:ans) cout << x << endl;
    return 0;
}

UVA 10200 Prime Time

计算结果加上1e-8可以避免0.50000被计算成0.499999的问题

代码

#define LOCAL
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef unsigned long long ll;
const ll mod = 1e9+7;
bool judge(int x){
    for(int i=2; i*i<=x; i++){
        if(x%i==0) return false;
    }
    return true;
}
map<int, int> sum;
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    //sum[0] = 1;
    FOR(i, 0, 10000){
        sum[i] = sum[i-1]+judge(i*i+i+41);
    }
    int a, b;
    while(cin >> a >> b){
        printf("%.2f\n", (double)(sum[b]-sum[a-1])/(b-a+1)*100+1e-8);
    }
    return 0;
}

UVA 11916 Emoogle Grid

当一个格子在第一行或者上方不能染色时,该格子染色方案为\(k\),否则为\(k-1\)。可以分别统计这两种格子的数目\(num1,num2\),则答案为\(r=k^{num1}*(k-1)^{num2}\)

先令\(m\)为不能染色的格子行数的最大值\(max\)(也就是行数可能的最小值),计算一次结果,如果和\(r\)不一样,再假设行数为\(max+1\),如果计算出来的答案\(ans2\)还和\(r\)不一样,之后每增加一行,就相当于多\(n\)个格子染\(k-1\)个颜色,有式子\(r=ans2*((k-1)^{n})^{x}\),用\(BSGS\)算法求出来x,答案即为\(max+x+1\)

这题我一个人wa了一整页,好丢人。。。

代码

#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
//#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
// 哈希BSGS O(sqrt(n)) a^x=b (mod n) a,n互质  
#define MOD 76543
ll hs[MOD], head[MOD], Next[MOD], id[MOD], top;
void insert(ll x, ll y){
    ll k = x%MOD;
    hs[top] = x, id[top] = y, Next[top] = head[k], head[k] = top++;
}
ll find(ll x){
    ll k = x%MOD;
    for(ll i=head[k]; i!=-1; i=Next[i]){
        if(hs[i]==x){
            return id[i];
        }
    }
    return -1;
}
ll BSGS(ll a, ll b, ll n){
    memset(head, -1, sizeof(head));
    top = 1;
    if(b==1) return 0;
    ll m = sqrt(n*1.0), j;
    ll x = 1, p = 1;
    for(ll i=0; i<m; i++, p=p*a%n) insert(p*b%n, i);
    for(ll i=m; ; i+=m){
        if((j=find(x=x*p%n))!=-1) return i-j;
        if(i>n) break;
    }
    return -1;
}
//pow(x,n)%mod O(logn)
ll mod_pow(ll x,ll n,ll mod)
{
    ll res=1;
    while(n>0){
        if(n&1) res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    ll T, _=0;
    cin >> T;
    while(T--){
        printf("Case %lld: ", ++_);
        ll n, k, b, r;
        cin >> n >> k >> b >> r;
        map<ll, map<ll, bool> > mp;
        vector<ll> x(b+1), y(b+1);
        ll mx = 1;
        FOR(i, 1, b){
            cin >> x[i] >> y[i];
            mp[x[i]][y[i]] = true;
            mx = max(mx, x[i]);
        }
        ll num1 = n, num2 = n*(mx-1);
        FOR(i, 1, b){
            if(x[i]==1){
                num1--;
            }
            else{
                num2--;
            }
            if(x[i]+1<=mx && !mp[x[i]+1][y[i]]) num2--, num1++;
        }
        ll base = mod_pow(k, num1, mod)*mod_pow(k-1, num2, mod)%mod;
        if(base==r){
            cout << mx << endl;
            continue;
        }
        num1 = n, num2 = n*mx;
        FOR(i, 1, b){
            if(x[i]==1){
                num1--;
            }
            else{
                num2--;
            }
            if(!mp[x[i]+1][y[i]]) num2--, num1++;
        }
        base = mod_pow(k, num1, mod)*mod_pow(k-1, num2, mod)%mod;
        ll ans = BSGS(mod_pow(k-1, n, mod), r*mod_pow(base, mod-2, mod)%mod, mod);
        cout << ans+mx+1 << endl;
    }
    return 0;
}

POJ 2116 Death to Binary?

将一个整数转化为\(canonical\ Fibonacci\ representation\)其实就是从大到小遍历斐波那契数,如果当前数字大于这个斐波那契数就减去它并且这一位表示为1否则表示为0。这道题一个数字最多就四十一位,所以从第四十一个斐波那契数开始遍历就行了。写两个函数,一个把斐波那契形式数字(字符串)转化为一个整数,一个把一个整数转化为斐波那契形式的字符串,之后的操作就很简单了

比较坑的是这个题\(fib[0]=1,fib[1]=2\)。还有当数字是0的时候,转化成字符串时要注意一下。

代码

#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
//#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
int fib[45];
int toNum(string s){
    int ans = 0;
    FOR(i, 0, s.length()-1){
        ans += fib[i]*(s[s.length()-1-i]-'0');
    }
    return ans;
}
string toString(int x){
    string s = "";
    ROF(i, 43, 0){
        if(x>=fib[i]){
            x -= fib[i];
            s += "1";
        }
        else if(s!=""){
            s += "0";
        }
    }
    if(s=="") s = "0";
    return s;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
    fib[0] = 1;
    fib[1] = 2;
    FOR(i, 2, 43) fib[i] = fib[i-1]+fib[i-2];
    string x, y;
    while(cin >> x >> y){
        int a = toNum(x);
        int b = toNum(y);
        int c = a+b;
        string p = toString(a), q = toString(b), r = toString(c);
        int w = r.length();
        FOR(i, 1, r.length()-p.length()+2) cout << " ";
        cout << p << endl;
        cout << "+";
        FOR(i, 1, r.length()-q.length()+1) cout << " ";
        cout << q << endl;
        cout << "  ";
        FOR(i, 1, r.length()) cout << "-";
        cout << endl;
        cout << "  " << r << endl << endl;
    }
    return 0;
}

UVA 11754 Code Feat

要计算出结果有两种做法,一个是dfs枚举所有余数组合再用中国剩余定理求解,另一种是选定一个除数x,对于他对应的余数r,枚举\(kx+r\)并筛选出符合条件的解

这两种方法交上去亲测都会TLE,第一种方法适用于余数较少的情况,第二种方法适用于余数较多的情况,所以可以根据余数的数量来选择不同的方式求解

代码

#define LOCAL
#include<iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
ll c, s;
ll x[15], b[15], t[11], k[11][105], bst, fact;
vector<ll> ans;
set<ll> st[15];

void sol2(){
	sort(k[bst]+1, k[bst]+t[bst]+1);
	for(ll i=0; s; i++){
		FOR(j, 1, t[bst]){
			bool ok = true;
			ll tmp = k[bst][j]+x[bst]*i;
			if(tmp==0) continue;
			FOR(p, 1, c){
				if(!st[p].count(tmp%x[p])){
					ok = false;
					break;
				}
			}
			if(ok){
				cout << tmp << endl;
				s--;
				if(!s) return;
			}
		}
	}
}

ll extgcd(ll aa,ll bb,ll &xx,ll &yy)
{
    ll d=aa;
    if(bb!=0){
        d=extgcd(bb,aa%bb,yy,xx);
        yy-=(aa/bb)*xx;
    }
    else{
        xx=1;yy=0;
    }
    return d;
}

void CRT(){
	ll res=0;
	FOR(i, 1, c){
		ll m = fact/x[i];
		ll inv, y;
		extgcd(m, x[i], inv, y);
		inv = (inv%x[i]+x[i])%x[i];
		res = (res+inv*m*b[i]%fact)%fact; // 解集形式为ans+kt;
	}
	ans.pb((res+fact)%fact);
}

void dfs(ll now){
	if(now==c+1){
		CRT();
		return;
	}
	FOR(i, 1, t[now]){
		b[now] = k[now][i];
		dfs(now+1);
	}
	return;
}

void sol1(){
	dfs(1);
	sort(ALL(ans));
	for(ll i=0; s; i++){
		for(auto val: ans){
			if(val+i*fact>0){
				cout << val+i*fact << endl;
				s--;
				if(!s) return;
			}
		}
	}
}

int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	while(cin >> c >> s && c && s){
		bst = 1;
		fact = 1;
		ans.clear();
		ll tot = 1;
		FOR(i, 1, c){
			st[i].clear();
			cin >> x[i];
			cin >> t[i];
			FOR(j, 1, t[i]) cin >> k[i][j], st[i].insert(k[i][j]);
			if(x[i]*t[bst]>t[i]*x[bst]) bst = i;
			tot *= t[i];
			fact *= x[i];
		}
		if(tot<=10000) sol1();
		else sol2();
		cout << endl;
	}
    return 0;
}

LightOJ 1356 Prime Independence

如果两个数满足\(a=b\ast prime\)则a与b素因子的个数必定为一奇一偶,所以可以按照每个数素因子个数的奇偶性建立二分图,存在\(a=b\ast prime\)关系的两个数之间连边,用\(HK\)算法求出最大独立集即可。

代码

#define LOCAL
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<cmath>
#include<stdio.h>
#include<utility>
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug(msg) cout << (msg) << endl
#define FOR(i, a, b) for (ll i=a; i<=(b); i++)
#define ROF(i, a, b) for (ll i=a; i>=(b); i--)
#define pb(x) push_back(x) 
#define ALL(x) x.begin(), x.end()
#define RALL(x) x.rbegin(), x.rend()
#define sz(x) (ll)x.size()
#define JUDGE(x) if(x) cout << "Yes\n"; else cout << "No\n";
using namespace std;
typedef long long ll;
const ll mod = 1e8+7;
// 合数分解
const int MAXN=40000;
int prime[MAXN+1];
void getPrime(){
	memset(prime, 0 ,sizeof(prime));
	for(int i=2; i<=MAXN; i++){
		if(!prime[i]) prime[++prime[0]] = i;
		for(int j=1; j<=prime[0]&&prime[j]<=MAXN/i; j++){
			prime[prime[j]*i] = 1;
			if(j%prime[j]==0) break;
		}
	}
}
ll factor[100][2];
int factCnt, factNum;
int getFactors(ll x){
	factCnt = 0;
	factNum = 0;
	ll temp = x;
	for(int i=1; prime[i]<=temp/prime[i] && i<=prime[0]; i++){
		factor[factCnt][1] = 0;
		if(temp%prime[i]==0){
			factor[factCnt][0] = prime[i];
			while(temp%prime[i]==0){
				factor[factCnt][1]++;
				temp /= prime[i];
			}
			factCnt++;
		}
	}
	if(temp!=1){
		factor[factCnt][0] = temp;
		factor[factCnt++][1] = 1;
	}
	FOR(i, 0, factCnt-1) factNum += factor[i][1];
	return factCnt;
}
// HK二分图最大匹配 uN为左侧顶点数 G存单向边 顶点编号从0开始 O(sqrt(n)*m)
const int maxn = 40001;
vector<int> G[maxn];
int uN;
int Mx[maxn], My[maxn];
int dx[maxn], dy[maxn];
int dis;
bool used[maxn];
bool searchP(){
	queue<int> Q;
	dis = INF;
	memset(dx, -1, sizeof(dx));
	memset(dy, -1, sizeof(dy));
	for(int i=0; i<uN; i++){
		if(Mx[i]==-1){
			Q.push(i);
			dx[i] = 0;
		}
	}
	while(!Q.empty()){
		int u = Q.front();
		Q.pop();
		if(dx[u]>dis) break;
		int sz = G[u].size();
		for(int i=0; i<sz; i++){
			int v = G[u][i];
			if(dy[v]==-1){
				dy[v] = dx[u]+1;
				if(My[v]==-1) dis = dy[v];
				else{
					dx[My[v]] = dy[v]+1;
					Q.push(My[v]);
				}
			}
		}
	}
	return dis != INF;
}
bool dfs(int u){
	int sz = G[u].size();
	for(int i=0; i<sz; i++){
		int v = G[u][i];
		if(!used[v] && dy[v]==dx[u]+1){
			used[v] = true;
			if(My[v]!=-1 && dy[v]==dis) continue;
			if(My[v]==-1 || dfs(My[v])){
				My[v] = u;
				Mx[u] = v;
				return true;
			}
		}
	}
	return false;
}
int maxMatch(){
	int res = 0;
	memset(Mx, -1, sizeof(Mx));
	memset(My, -1, sizeof(My));
	while(searchP()){
		memset(used, false, sizeof(used));
		for(int i=0; i<uN; i++){
			if(Mx[i]==-1 && dfs(i)){
				res++;
			}
		}
	}
	return res;
}
int main()
{
	#ifdef LOCAL
		freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
	#endif
	getPrime();
	int T, _=0;
	cin >> T;
	while(T--){
		int n, cnt=0;
		uN = 0;
		cin >> n;
		vector<int> a(n+1);
		map<int, int> mp;
		vector<int> lft, ri;
		FOR(i, 1, n){
			scanf("%d", &a[i]);
		}
		FOR(i, 1, n){
			getFactors(a[i]);
			if(factNum%2){
				G[uN].clear();
				lft.pb(a[i]);
				mp[a[i]] = ++uN;
			}
			else{
				mp[a[i]] = ++cnt;
				ri.pb(a[i]);
			}
		}
		if(uN){
			FOR(i, 0, lft.size()-1){
				getFactors(lft[i]);
				FOR(j, 0, factCnt-1){
					if(mp[lft[i]/factor[j][0]]){
						G[i].pb(mp[lft[i]/factor[j][0]]);
					}
				}
			}
		}
		if(cnt){
			FOR(i, 0, ri.size()-1){
				getFactors(ri[i]);
				FOR(j, 0, factCnt-1){
					if(mp[ri[i]/factor[j][0]]){
						G[mp[ri[i]/factor[j][0]]-1].pb(i+1);
					}
				}
			}
		}
		printf("Case %d: %d\n", ++_, n-maxMatch());
	}
    return 0;
}
posted @ 2021-02-20 00:16  DinoMax  阅读(137)  评论(0)    收藏  举报